/** * Add a listener that is notified when routes change for the registry. * * @param listener * listener to add * @return registration for removing the listener */ public Registration addRoutesChangeListener( RoutesChangedListener listener) { return handledRegistry.addRoutesChangeListener(listener); }
/** * Gets the optional navigation target class for a given Location matching * with path segments. * * @param pathString * path to get navigation target for, not {@code null} * @param segments * segments given for path * @return optional navigation target corresponding to the given path and * segments */ public Optional<Class<? extends Component>> getRoute(String pathString, List<String> segments) { return handledRegistry.getNavigationTarget(pathString, segments); }
/** * Get the {@link RouteData} for all registered navigation targets. * <p> * Note! This would be best to request for session scope registry as it will * then contain the actual currently visible routes from both the session * and application scopes. * <p> * Note! Size of the list is only main routes as RouteData will contain a * list of alias route registrations. * * @return list of all routes available */ public List<RouteData> getAvailableRoutes() { return handledRegistry.getRegisteredRoutes(); }
@SuppressWarnings("unchecked") @Override public void contextInitialized(ServletContextEvent event) { ApplicationRouteRegistry registry = ApplicationRouteRegistry .getInstance(event.getServletContext()); if (registry.getRegisteredRoutes().isEmpty()) { try { List<Class<?>> routeClasses = findByAnnotation( getRoutePackages(), Route.class, RouteAlias.class).collect(Collectors.toList()); Set<Class<? extends Component>> navigationTargets = validateRouteClasses( routeClasses.stream()); RouteConfiguration routeConfiguration = RouteConfiguration .forRegistry(registry); routeConfiguration.update(() -> { routeConfiguration.getHandledRegistry().clean(); navigationTargets.forEach(routeConfiguration::setAnnotatedRoute); }); registry.setPwaConfigurationClass(validatePwaClass(routeClasses.stream())); } catch (InvalidRouteConfigurationException e) { throw new IllegalStateException(e); } } }
/** * Check if the route is available as a registered target. * * @param route * target class to check for registration * @return true if class is registered */ public boolean isRouteRegistered(Class<? extends Component> route) { return handledRegistry.getTargetUrl(route).isPresent(); }
private static Class<? extends RouterLayout> getTopParentLayout( Router router, NavigationState navigationState) { List<Class<? extends RouterLayout>> routeLayouts = router.getRegistry() .getRouteLayouts(navigationState.getResolvedPath(), navigationState.getNavigationTarget()); if (routeLayouts.isEmpty()) { return null; } return routeLayouts.get(routeLayouts.size() - 1); } }
/** * Register a navigation target with specified path and given parent layout * chain. * <p> * Note! Any {@link ParentLayout}, {@link Route} or {@link RouteAlias} will * be ignored in route handling. * * @param path * path to register navigation target to * @param navigationTarget * navigation target to register * @param parentChain * chain of parent layouts that should be used with this target * @throws InvalidRouteConfigurationException * thrown if exact route already defined in this scope */ public void setRoute(String path, Class<? extends Component> navigationTarget, List<Class<? extends RouterLayout>> parentChain) { handledRegistry.setRoute(path, navigationTarget, parentChain); }
/** * Remove the given navigation target route registration. Path where the * navigation target was may still be usable, e.g. we remove target with url * param and there is left a non param target, but will not return the * removed target. * <p> * Note! this will remove target route and if possible any * {@link RouteAlias} route that can be found for the class. * * @param navigationTarget * navigation target class to remove */ public void removeRoute(Class<? extends Component> navigationTarget) { handledRegistry.removeRoute(navigationTarget); }
/** * Block updates to the registry configuration from other threads until * update command has completed. * <p> * Using this method makes the registry changes made inside the command * atomic for the registry as no one else can change the state during the * duration of the command. * <p> * Any other configuration thread for the same registry will be blocked * until all the update locks have been released. * <p> * Note! During an update other threads will get the pre-update state of the * registry until the update has fully completed. * * @param command * command to execute for the update */ public void update(Command command) { handledRegistry.update(command); }
@Override public void onStartup(Set<Class<?>> classSet, ServletContext servletContext) throws ServletException { try { if (classSet == null) { ApplicationRouteRegistry routeRegistry = ApplicationRouteRegistry .getInstance(servletContext); routeRegistry.clean(); return; } Set<Class<? extends Component>> routes = validateRouteClasses( classSet.stream()); ApplicationRouteRegistry routeRegistry = ApplicationRouteRegistry .getInstance(servletContext); RouteConfiguration routeConfiguration = RouteConfiguration .forRegistry(routeRegistry); routeConfiguration.update(() -> { routeConfiguration.getHandledRegistry().clean(); for (Class<? extends Component> navigationTarget : routes) { routeConfiguration.setAnnotatedRoute(navigationTarget); } }); routeRegistry.setPwaConfigurationClass(validatePwaClass( routes.stream().map(clazz -> (Class<?>) clazz))); } catch (InvalidRouteConfigurationException irce) { throw new ServletException( "Exception while registering Routes on servlet startup", irce); } }
private String getUrlForTarget(Class<? extends Component> navigationTarget, RouteRegistry registry) { Optional<String> targetUrl = registry.getTargetUrl(navigationTarget); if (!targetUrl.isPresent()) { throw new NotFoundException( "No route found for given navigation target!"); } return targetUrl.get(); }
@Override public List<Class<? extends RouterLayout>> getRouteLayouts(String path, Class<? extends Component> navigationTarget) { if (getConfiguration().hasRoute(path)) { return super.getRouteLayouts(path, navigationTarget); } return parentRegistry.getRouteLayouts(path, navigationTarget); } }
/** * Register a navigation target with specified path and given parent layout * chain. * <p> * Note! Any {@link ParentLayout}, {@link Route} or {@link RouteAlias} will * be ignored in route handling. * * @param path * path to register navigation target to * @param navigationTarget * navigation target to register * @param parentChain * chain of parent layouts that should be used with this target * @throws InvalidRouteConfigurationException * thrown if exact route already defined in this scope */ // This method is unchecked for the type due to varargs public void setRoute(String path, Class<? extends Component> navigationTarget, Class<? extends RouterLayout>... parentChain) { handledRegistry .setRoute(path, navigationTarget, Arrays.asList(parentChain)); }
/** * Remove all registrations for given path. This means that any navigation * target registered on the given path will be removed. But if a removed * navigationTarget for the path exists it is then stored with a new main * path so it can still get a resolved url. * <p> * E.g. path "home" contains HomeView and DetailsView[String path param] * both will be removed. * <p> * Note! The restored path will be the first found match for all paths that * are registered. * * @param path * path for which to remove all navigation targets */ public void removeRoute(String path) { handledRegistry.removeRoute(path); }
private Class<? extends Component> getNavigationTargetWithParameter( RouteRegistry registry, String path, List<String> segments) throws NotFoundException { return registry.getNavigationTarget(path, segments) .orElseThrow(() -> new NotFoundException(String.format( "No navigation target found for path '%s'.", path))); }
@Override public Optional<String> getTargetUrl( Class<? extends Component> navigationTarget) { Optional<String> targetUrl = super.getTargetUrl(navigationTarget); if (targetUrl.isPresent()) { return targetUrl; } return parentRegistry.getTargetUrl(navigationTarget); }
@Override public List<RouteData> getRegisteredRoutes() { List<RouteData> routes = new ArrayList<>(super.getRegisteredRoutes()); List<RouteData> registeredRoutes = parentRegistry.getRegisteredRoutes(); if (!registeredRoutes.isEmpty()) { Set<String> collect = routes.stream().map(RouteData::getUrl) .collect(Collectors.toSet()); registeredRoutes.stream() .filter(data -> !collect.contains(data.getUrl())) .forEach(routes::add); } return routes; }
if (Component.class.isAssignableFrom(navigationTarget)) { List<Class<? extends RouterLayout>> routeLayouts = ui.getRouter() .getRegistry().getRouteLayouts(path, (Class<? extends Component>) navigationTarget); topParentLayout = routeLayouts.isEmpty() ? null
/** * Register a navigation target on the specified path. Any * {@link ParentLayout} annotation on class will be used to populate layout * chain, but {@link Route} and {@link RouteAlias} will not be taken into * consideration. * * @param path * path to register navigation target to * @param navigationTarget * navigation target to register * @throws InvalidRouteConfigurationException * thrown if exact route already defined in this scope */ public void setParentAnnotatedRoute(String path, Class<? extends Component> navigationTarget) { handledRegistry.setRoute(path, navigationTarget, RouteUtil.getParentLayoutsForNonRouteTarget(navigationTarget)); }
private void subscribeToChanges(RouteRegistry routeRegistry) { subscribingRegistrations.add(routeRegistry.addRoutesChangeListener( event -> update(() -> applyChange(event)))); }