package org.webpieces.router.impl.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.webpieces.ctx.api.RouterRequest;
import org.webpieces.router.impl.RouteMeta;
public class L3PrefixedRouting {
final Map<String, L3PrefixedRouting> pathPrefixToInfo = new HashMap<>();
List<RouteMeta> routes = new ArrayList<>();
public L3PrefixedRouting getScopedRouter(String fullPath) {
String[] split = splitInTwo(fullPath);
String path = fullPath;
if(split != null)
path = split[0];
L3PrefixedRouting r = pathPrefixToInfo.get(path);
if(r == null) {
r = new L3PrefixedRouting();
pathPrefixToInfo.put(path, r);
}
if(split == null)
return r;
else
return r.getScopedRouter(split[1]);
}
private String[] splitInTwo(String fullPath) {
if(!fullPath.startsWith("/"))
throw new IllegalArgumentException("fullPath should start with a / but did not");
int indexOf = fullPath.indexOf("/", 1);
if(indexOf < 0)
return null;
String path = fullPath.substring(0, indexOf);
String leftover = fullPath.substring(indexOf);
return new String[] {path, leftover};
}
public void addRoute(RouteMeta meta) {
routes.add(meta);
}
public MatchResult fetchRoute(RouterRequest request, String subPath) {
if("".equals(subPath))
return findRouteMatch(routes, request, subPath);
else if(!subPath.startsWith("/"))
throw new IllegalArgumentException("path must start with /");
String prefix = subPath;
int index = subPath.indexOf("/", 1);
if(index == 1) {
throw new IllegalArgumentException("path cannot start with //");
} else if(index > 1) {
prefix = subPath.substring(0, index);
}
L3PrefixedRouting routeInfo = pathPrefixToInfo.get(prefix);
if(routeInfo != null) {
if(index < 0)
return routeInfo.fetchRoute(request, "");
String newRelativePath = subPath.substring(index, subPath.length());
MatchResult route = routeInfo.fetchRoute(request, newRelativePath);
if(route != null)
return route;
}
return findRouteMatch(routes, request, subPath);
}
public MatchResult findRouteMatch(List<RouteMeta> routes, RouterRequest request, String subPath) {
for(RouteMeta meta : routes) {
MatchResult result = meta.matches(request, subPath);
if(result != null)
return result;
}
return new MatchResult(false);
}
}