/**
* Copyright (c) 2002-2011 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.smack.routing;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.MatchResult;
import org.apache.log4j.Logger;
import com.sun.jersey.server.impl.uri.PathPattern;
import com.sun.jersey.server.impl.uri.PathTemplate;
public class Router extends RoutingDefinition {
private RouteEntry [] routes;
private static final Logger logger = Logger.getLogger(Router.class);
private static Endpoint notFoundEndpoint = new NotFoundEndpoint();
private final ResettableQueryStringDecoder queryStringDecoder = new ResettableQueryStringDecoder();
public Endpoint route(Routable routable)
{
String path = routable.getPath();
queryStringDecoder.resetWith(path);
routable.getPathVariables().add(queryStringDecoder.getParameters());
// TODO: parallelize routing ?? (overhead ?)
// Potentially desert the regex approach and go
// with something that builds a tree structure with the path
// segments of the enpoint paths, traversing it to find endpoint?
for(RouteEntry route : routes)
{
MatchResult matchResult = route.pattern.match(path);
if(matchResult != null)
{
Endpoint endpoint = route.getEndpoint(routable.getVerb());
if(endpoint != null) {
routable.getPathVariables().add(matchResult, route.pattern); // todo is this the best way ?
return endpoint;
}
return notFoundEndpoint;
}
}
return notFoundEndpoint;
}
public void compileRoutes() {
Map<String, RouteEntry> routeMap = new LinkedHashMap<String, RouteEntry>();
for(RouteDefinitionEntry definition : getRouteDefinitionEntries())
{
if(!routeMap.containsKey(definition.getPath()))
{
logger.debug("Adding Route: "+definition.getEndpoint().getVerb() +" to: "+ definition.getPath());
routeMap.put(definition.getPath(), createRoute(definition));
}
RouteEntry route = routeMap.get(definition.getPath());
route.setEndpoint(definition.getEndpoint().getVerb(), definition.getEndpoint());
// todo what happens if multiple paths have differnt verbs?
}
// Debug print routing table
// for(RouteEntry route : routeMap.values())
// System.out.println(route);
routes = routeMap.values().toArray(new RouteEntry[routeMap.size()]);
}
private RouteEntry createRoute(RouteDefinitionEntry definition) {
RouteEntry route = new RouteEntry();
final PathTemplate template = new PathTemplate(definition.getPath());
route.pattern = new PathPattern(template, definition.getPath().equals("") ? "/" : "");
return route;
}
}