/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.web.route; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; /** * MatchMaker class * * @author (Fei) John Chen * */ public class MatchMaker { private static final MatchMaker me = new MatchMaker(); private RootRoute rootRoute; private List<DefaultRoute> defaultRoutes = new ArrayList<DefaultRoute>(); private List<NamedRoute> namedRoutes = new ArrayList<NamedRoute>(); private List<RegularRoute> regularRoutes = new ArrayList<RegularRoute>(); private List<RestRoute> restRoutes = new ArrayList<RestRoute>(); private Map<String, RouteInfo> requestRouteMap = new HashMap<String, RouteInfo>(); private Map<String, Resource> resourceMap = new HashMap<String, Resource>(); private static List<Route> allRoutes = new ArrayList<Route>(); private MatchMaker() { } public static MatchMaker getInstance() { return me; } public List<Route> getAllRoutes() { return allRoutes; } public int countRoutes() { return allRoutes.size(); } public Route getRoute(String routeName) { return getRouteFromList(routeName, allRoutes); } public RootRoute getRootRoute() { return rootRoute; } public RootRoute getRootRoute(String routeName) { RootRoute r = null; if (rootRoute != null) { if (rootRoute.getName().equals(routeName)) { r = rootRoute; } } return r; } public void setRootRoute(RootRoute route) { rootRoute = route; allRoutes.add(route); } public DefaultRoute getDefaultRoute(String routeName) { return (DefaultRoute)getRouteFromList(routeName, defaultRoutes); } public void addDefaultRoute(DefaultRoute route) { defaultRoutes.add(route); allRoutes.add(route); } public void addDefaultRoutes(List<DefaultRoute> routes) { defaultRoutes.addAll(routes); allRoutes.addAll(routes); } public NamedRoute getNamedRoute(String routeName) { return (NamedRoute)getRouteFromList(routeName, namedRoutes); } public void addNamedRoute(NamedRoute route) { namedRoutes.add(route); allRoutes.add(route); } public void addNamedRoutes(List<NamedRoute> routes) { namedRoutes.addAll(routes); allRoutes.addAll(routes); } public RegularRoute getRegularRoute(String routeName) { return (RegularRoute)getRouteFromList(routeName, regularRoutes); } public void addRegularRoute(RegularRoute route) { regularRoutes.add(route); allRoutes.add(route); } public void addRegularRoutes(List<RegularRoute> routes) { regularRoutes.addAll(routes); allRoutes.addAll(routes); } public RestRoute getRestRoute(String routeName) { return (RestRoute)getRouteFromList(routeName, restRoutes); } public void addRestRoute(RestRoute route) { restRoutes.add(route); allRoutes.add(route); } public void addRestRoutes(List<RestRoute> routes) { restRoutes.addAll(routes); allRoutes.addAll(routes); } public Map<String, Resource> getResourceMap() { return resourceMap; } /** * Checks if a resource name is already added as a resource. * @param resourceName * @return true if the <tt>resourceName</tt> is not a resource already added. */ public boolean isAddedResource(String resourceName) { return (getResource(resourceName) != null)?true:false; } /** * Returns resource corresponding to a resource name. * * @param resourceName resource name * @return resource */ public Resource getResource(String resourceName) { return resourceMap.get(resourceName); } /** * Returns resource corresponding to a model name. * * @param model model name * @return resource */ public Resource getResourceForModel(String model) { Resource resource = null; for (Map.Entry<String, Resource> entry : resourceMap.entrySet()) { Resource res = entry.getValue(); if (model.equals(res.getModel())) { resource = res; break; } } return resource; } public void addResource(String resourceName, Resource resource) { resourceMap.put(resourceName, resource); } public void clear() { rootRoute = null; defaultRoutes.clear(); namedRoutes.clear(); regularRoutes.clear(); restRoutes.clear(); allRoutes.clear(); requestRouteMap.clear(); resourceMap.clear(); } public RouteInfo match(RequestInfo requestInfo) { if ("/".equals(requestInfo.getRequestPath())) return null; String requestKey = requestInfo.getRequestKey(); RouteInfo routeInfo = requestRouteMap.get(requestKey); if (routeInfo != null) { return routeInfo; } Route route = null; int index = -1; int size = allRoutes.size(); for (int i = 0; i < size; i++) { index = i; Route r = allRoutes.get(i); if (r.isRouteFor(requestInfo)) { route = r; break; } } boolean autoRestified = RouteConfig.getInstance().allowAutoREST(); if (route == null) { if (autoRestified) { String name = requestInfo.getAutoResourceName(); if (!isAddedResource(name)) { Resource resource = new Resource(name, Resource.PLURAL, new Properties(), false, true); //make sure the default routes are the last allRoutes.removeAll(defaultRoutes); addRestRoutes(resource.getRoutes()); allRoutes.addAll(defaultRoutes); addResource(name, resource); return match(requestInfo); } } } if (route == null) { throw new NoRouteFoundException(requestKey); } routeInfo = route.getRouteInfo(requestInfo); routeInfo.setIndex(index); requestRouteMap.put(requestKey, routeInfo); return routeInfo; } private Route getRouteFromList(String routeName, List<? extends Route> routes) { if (routeName == null || routes == null || routes.size() == 0) return null; Route route = null; for (Route r : routes) { if (routeName.equals(r.getName())) { route = r; break; } } return route; } }