/** * Create a copy of this RouteTarget. * * @param mutable * if created copy is mutable or not * @return copy of this RouteTarget */ public RouteTarget copy(boolean mutable) { RouteTarget copy = new RouteTarget(mutable); copy.normal = normal; copy.parameter = parameter; copy.optionalParameter = optionalParameter; copy.wildCardParameter = wildCardParameter; parentLayouts.keySet().forEach( key -> copy.parentLayouts.put(key, parentLayouts.get(key))); return copy; }
/** * Add a new route navigation target. * <p> * When adding a new target it will be validated that it is a valid path to * add with the already existing navigation targets. * * @param target * navigation target to add * @throws InvalidRouteConfigurationException * exception for miss configured routes where navigation targets * can not be clearly selected */ public void addRoute(Class<? extends Component> target) { throwIfImmutable(); addTargetByType(target); }
/** * Set the parent layout chain for target component. This will override any * existing parent layout chain for the target. * <p> * Note! if adding parents for a non registered target an * IllegalArgumentException will be thrown. * * @param target * target to add chain for * @param parents * parent layout chain */ public void setParentLayouts(Class<? extends Component> target, List<Class<? extends RouterLayout>> parents) { throwIfImmutable(); if (!containsTarget(target)) { throw new IllegalArgumentException( "Tried to add parent layouts for a non existing target " + target.getName()); } parentLayouts.put(target, Collections.unmodifiableList(new ArrayList<>(parents))); }
private void addTargetByType(Class<? extends Component> target) { if (!HasUrlParameter.class.isAssignableFrom(target) && !isAnnotatedParameter(target)) { validateNormalTarget(target); normal = target; } else { if (ParameterDeserializer .isAnnotatedParameter(target, OptionalParameter.class)) { validateOptionalParameter(target); optionalParameter = target; } else if (ParameterDeserializer .isAnnotatedParameter(target, WildcardParameter.class)) { validateWildcard(target); wildCardParameter = target; } else { validateParameter(target); parameter = target; } } }
/** * Remove specific navigation target for given route. The path will still * exist if there is another target with different parameters registered to * it. If no targets remain the path will be removed completely. * <p> * In case there exists another path mapping for the removed route * target the main class-to-string mapping will be updated to the first * found. * * @param path * path to remove target from * @param targetRoute * target route to remove from path */ public void removeRoute(String path, Class<? extends Component> targetRoute) { if (!hasRoute(path) || !getRoutesMap().get(path) .containsTarget(targetRoute)) { return; } RouteTarget routeTarget = getRoutesMap().get(path); routeTarget.remove(targetRoute); if (routeTarget.isEmpty()) { getRoutesMap().remove(path); } if (getTargetRoutes().containsKey(targetRoute) && getTargetRoutes() .get(targetRoute).equals(path)) { updateMainRouteTarget(targetRoute); } }
/** * Set a new {@link RouteTarget} for the given path. * <p> * Note! this will override any previous value. * * @param path * path for which to set route target for * @param navigationTarget * navigation target to add */ public void setRoute(String path, Class<? extends Component> navigationTarget) { if (hasRoute(path)) { getRoutesMap().get(path).addRoute(navigationTarget); } else { getRoutesMap().computeIfAbsent(path, key -> new RouteTarget(navigationTarget, true)); } }
/** * Remove the targetRoute completely from the configuration. * * @param targetRoute * target registered route to remove */ public void removeRoute(Class<? extends Component> targetRoute) { if (!hasRouteTarget(targetRoute)) { return; } // Remove target route from class-to-string map getTargetRoutes().remove(targetRoute); List<String> emptyRoutes = new ArrayList<>(); // Remove all instances of the route class for any path // that it may be registered to getRoutesMap().forEach((route, routeTarget) -> { routeTarget.remove(targetRoute); if (routeTarget.isEmpty()) { emptyRoutes.add(route); } }); emptyRoutes.forEach(getRoutesMap()::remove); }
private List<Class<? extends RouterLayout>> getParentLayouts( ConfiguredRoutes configuration, Class<? extends Component> target, String url) { RouteTarget routeTarget = configuration.getRouteTarget(url); if (routeTarget != null) { return routeTarget.getParentLayouts(target); } return Collections.emptyList(); }
/** * Check if navigation target is present in current target. * * @param target * navigation target to check for * @return true if navigation target is found in some position */ public boolean containsTarget(Class<? extends Component> target) { return getRoutes().contains(target); }
/** * Get the route class matching the given path and path segments. * * @param pathString * string to get the route for * @param segments * possible path segments * @return {@link Optional} containing the navigationTarget class if found */ public Optional<Class<? extends Component>> getRoute(String pathString, List<String> segments) { if (getRoutesMap().containsKey(pathString)) { RouteTarget routeTarget = getRoutesMap().get(pathString); return Optional.ofNullable(routeTarget.getTarget(segments)); } return Optional.empty(); }
/** * Collect all routes for which given routeTarget is registered. * This is mainly for handling route aliases as reading from the class * annotations doesn't specifically return the actual registartions as they * can change during runtime. * * @param routeTarget * route target to collect registered paths for * @return list of routes this routeTarget is registered for */ protected List<String> getRoutePaths( Class<? extends Component> routeTarget) { return getRoutesMap().entrySet().stream() .filter(entry -> entry.getValue().containsTarget(routeTarget)) .map(Map.Entry::getKey).collect(Collectors.toList()); }
/** * Create a mutable or immutable configuration with original configuration * information. * * @param original * original configuration to get data from */ public ConfigureRoutes(ConfiguredRoutes original) { Map<String, RouteTarget> routesMap = new HashMap<>(); Map<Class<? extends Component>, String> targetRoutesMap = new HashMap<>(); Map<Class<? extends Exception>, Class<? extends Component>> exceptionTargetsMap = new HashMap<>(); for (Map.Entry<String, RouteTarget> route : original.getRoutesMap() .entrySet()) { routesMap.put(route.getKey(), route.getValue().copy(true)); } targetRoutesMap.putAll(original.getTargetRoutes()); exceptionTargetsMap.putAll(original.getExceptionHandlers()); this.routeMap = routesMap; this.targetRouteMap = targetRoutesMap; this.exceptionTargetMap = exceptionTargetsMap; }
/** * Create a new Route target holder with the given target registered. * * @param target * navigation target * @param mutable * if this should be mutable * @throws InvalidRouteConfigurationException * exception for miss configured routes where navigation targets * can not be clearly selected */ public RouteTarget(Class<? extends Component> target, boolean mutable) { this.mutable = mutable; addTargetByType(target); }
/** * Return the parent layout chain for given navigation target on the target * path. * * @param path * path to get parent layout chain for * @param navigationTarget * navigation target on path to get parent layout chain for * @return list of parent layout chain */ public List<Class<? extends RouterLayout>> getParentLayouts(String path, Class<? extends Component> navigationTarget) { return getRoutesMap().get(path).getParentLayouts(navigationTarget); }
/** * Remove route for given path. This will remove all targets registered for * given path. * <p> * In case there exists another path mapping for any of the removed route * targets the main class-to-string mapping will be updated to the first * found. * * @param path * path from which to remove routes from */ public void removeRoute(String path) { if (!hasRoute(path)) { return; } RouteTarget removedRoute = getRoutesMap().remove(path); for (Class<? extends Component> targetRoute : removedRoute .getRoutes()) { updateMainRouteTarget(targetRoute); } }
/** * Check if configuration holds a route for given path with possible path * segments. * * @param pathString * path string to check * @param segments * path segments for route * @return true if a route is found, else false */ public boolean hasRoute(String pathString, List<String> segments) { if (getRoutesMap().containsKey(pathString)) { return getRoutesMap().get(pathString).getTarget(segments) != null; } return false; }
/** * Update the main route target for the navigationTarget if another route * for the class is found. * * @param navigationTarget * navigation target to update the main route for */ private void updateMainRouteTarget( Class<? extends Component> navigationTarget) { getTargetRoutes().remove(navigationTarget); // Update Class-to-string map with a new mapping if removed route exists for another path for (Map.Entry<String, RouteTarget> entry : getRoutesMap().entrySet()) { if (entry.getValue().containsTarget(navigationTarget)) { getTargetRoutes().put(navigationTarget, entry.getKey()); return; } } } }
/** * Create a mutable or immutable configuration with original configuration * information. * * @param original * original configuration to get data from */ public ConfiguredRoutes(ConfigureRoutes original) { Map<String, RouteTarget> routeMap = new HashMap<>(); Map<Class<? extends Component>, String> targetRouteMap = new HashMap<>(); Map<Class<? extends Exception>, Class<? extends Component>> exceptionTargetMap = new HashMap<>(); for (Map.Entry<String, RouteTarget> route : original.getRoutesMap() .entrySet()) { routeMap.put(route.getKey(), route.getValue().copy(false)); } targetRouteMap.putAll(original.getTargetRoutes()); exceptionTargetMap.putAll(original.getExceptionHandlers()); this.routes = routeMap.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(routeMap); this.targetRoutes = targetRouteMap.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(targetRouteMap); this.exceptionTargets = exceptionTargetMap.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(exceptionTargetMap); }