/*
 * Copyright 2019 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */
package io.vertx.ext.web.impl;

import io.vertx.core.Handler;
import io.vertx.ext.web.AllowForwardHeaders;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;

import java.util.*;

This class encapsulates the router state, all mutations are atomic and return a new state with the mutation.

This class is thread-safe

Author:Paulo Lopes
/** * This class encapsulates the router state, all mutations are atomic and return a new state with the mutation. * <p> * This class is thread-safe * * @author <a href="http://pmlopes@gmail.com">Paulo Lopes</a> */
final class RouterState { private static final Comparator<RouteImpl> routeComparator = (RouteImpl o1, RouteImpl o2) -> { // we keep a set of handlers ordered by its "order" property final int compare = Integer.compare(o1.order(), o2.order()); // since we are defining the comparator to order the set we must be careful because the set // will use the comparator to compare the identify of the handlers and if they are the same order // are assumed to be the same comparator and therefore removed from the set. // if the 2 routes being compared by its order have the same order property value, // then do a more expensive equality check and if and only if the are the same we // do return 0, meaning same order and same identity. if (compare == 0) { if (o1.equals(o2)) { return 0; } // otherwise we return higher so if 2 routes have the same order the second one will be considered // higher so it is added after the first. return 1; } return compare; }; private final RouterImpl router; private final Set<RouteImpl> routes; private final int orderSequence; private final Map<Integer, Handler<RoutingContext>> errorHandlers; private final Handler<Router> modifiedHandler; private final AllowForwardHeaders allowForward; public RouterState(RouterImpl router, Set<RouteImpl> routes, int orderSequence, Map<Integer, Handler<RoutingContext>> errorHandlers, Handler<Router> modifiedHandler, AllowForwardHeaders allowForward) { this.router = router; this.routes = routes; this.orderSequence = orderSequence; this.errorHandlers = errorHandlers; this.modifiedHandler = modifiedHandler; this.allowForward = allowForward; } public RouterState(RouterImpl router) { this( router, null, 0, null, null, AllowForwardHeaders.NONE); } public RouterImpl router() { return router; } public Set<RouteImpl> getRoutes() { if (routes == null) { return Collections.emptySet(); } return routes; } RouterState setRoutes(Set<RouteImpl> routes) { RouterState newState = new RouterState( this.router, new TreeSet<>(routeComparator), this.orderSequence, this.errorHandlers, this.modifiedHandler, this.allowForward); newState.routes.addAll(routes); return newState; } RouterState addRoute(RouteImpl route) { Set<RouteImpl> routes = new TreeSet<>(routeComparator); if (this.routes != null) { routes.addAll(this.routes); } routes.add(route); return new RouterState( this.router, routes, this.orderSequence, this.errorHandlers, this.modifiedHandler, this.allowForward); } RouterState clearRoutes() { return new RouterState( this.router, new TreeSet<>(routeComparator), this.orderSequence, this.errorHandlers, this.modifiedHandler, this.allowForward); } RouterState removeRoute(RouteImpl route) { Set<RouteImpl> routes = new TreeSet<>(routeComparator); if (this.routes != null) { routes.addAll(this.routes); } routes.remove(route); return new RouterState( this.router, routes, this.orderSequence, this.errorHandlers, this.modifiedHandler, this.allowForward); } public int getOrderSequence() { return orderSequence; } RouterState incrementOrderSequence() { return new RouterState( this.router, this.routes, this.orderSequence + 1, this.errorHandlers, this.modifiedHandler, this.allowForward); } RouterState setOrderSequence(int orderSequence) { return new RouterState( this.router, this.routes, orderSequence, this.errorHandlers, this.modifiedHandler, this.allowForward); } public Map<Integer, Handler<RoutingContext>> getErrorHandlers() { return errorHandlers; } RouterState setErrorHandlers(Map<Integer, Handler<RoutingContext>> errorHandlers) { return new RouterState( this.router, this.routes, this.orderSequence, errorHandlers, this.modifiedHandler, this.allowForward); } Handler<RoutingContext> getErrorHandler(int errorCode) { if (errorHandlers != null) { return errorHandlers.get(errorCode); } return null; } RouterState putErrorHandler(int errorCode, Handler<RoutingContext> errorHandler) { RouterState newState = new RouterState( this.router, this.routes, this.orderSequence, this.errorHandlers == null ? new HashMap<>() : new HashMap<>(errorHandlers), this.modifiedHandler, this.allowForward); newState.errorHandlers.put(errorCode, errorHandler); return newState; } public Handler<Router> getModifiedHandler() { return modifiedHandler; } public RouterState setModifiedHandler(Handler<Router> modifiedHandler) { return new RouterState( this.router, this.routes, this.orderSequence, this.errorHandlers, modifiedHandler, this.allowForward); } public RouterState setAllowForward(AllowForwardHeaders allow) { return new RouterState( this.router, this.routes, this.orderSequence, this.errorHandlers, this.modifiedHandler, allow); } public AllowForwardHeaders getAllowForward() { return allowForward; } @Override public String toString() { return "RouterState{" + "routes=" + routes + ", orderSequence=" + orderSequence + ", errorHandlers=" + errorHandlers + ", modifiedHandler=" + modifiedHandler + ", this.allowForward=" + allowForward + '}'; } }