package org.webpieces.router.impl;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import org.webpieces.ctx.api.RouterRequest;
import org.webpieces.router.api.BodyContentBinder;
import org.webpieces.router.api.actions.Action;
import org.webpieces.router.api.dto.MethodMeta;
import org.webpieces.router.impl.model.MatchResult;
import org.webpieces.router.impl.model.RouteModuleInfo;
import org.webpieces.util.filters.Service;
import com.google.inject.Injector;
public class RouteMeta {
private final Route route;
private RouteModuleInfo routeModuleInfo;
private Injector injector;
private Charset urlEncoding;
private List<FilterInfo<?>> filtersToApply = new ArrayList<>();
private Service<MethodMeta, Action> filtersAndMethodToCall;
private Object controllerInstance;
private Method method;
private List<String> methodParamNames;
private BodyContentBinder bodyContentBinder;
public RouteMeta(Route r, Injector injector, RouteModuleInfo routerInfo, Charset urlEncoding) {
if(routerInfo == null)
throw new IllegalArgumentException("routerInfo must be non-null");
this.route = r;
this.routeModuleInfo = routerInfo;
this.injector = injector;
this.urlEncoding = urlEncoding;
}
public Route getRoute() {
return route;
}
public Object getControllerInstance() {
return controllerInstance;
}
public Method getMethod() {
return method;
}
public void setControllerInstance(Object controllerInstance) {
this.controllerInstance = controllerInstance;
}
public void setMethod(Method method) {
this.method = method;
}
public void setMethodParamNames(List<String> paramNames) {
this.methodParamNames = paramNames;
}
public MatchResult matches(RouterRequest request, String subPath) {
Matcher matcher = route.matches(request, subPath);
if(matcher == null)
return null;
else if(!matcher.matches())
return null;
List<String> names = route.getPathParamNames();
Map<String, String> namesToValues = new HashMap<>();
for(String name : names) {
String value = matcher.group(name);
if(value == null)
throw new IllegalArgumentException("Bug, something went wrong. request="+request);
//convert special characters back to their normal form like '+' to ' ' (space)
String decodedVal = urlDecode(value);
namesToValues.put(name, decodedVal);
}
return new MatchResult(this, namesToValues);
}
@Override
public String toString() {
return "\nRouteMeta [route=\n " + route + ", \n method=" + method
+ ",\n methodParamNames=" + methodParamNames + "]";
}
public String getPackageContext() {
return routeModuleInfo.packageName;
}
public String getI18nBundleName() {
return routeModuleInfo.i18nBundleName;
}
public Injector getInjector() {
return injector;
}
private String urlDecode(Object value) {
try {
return URLDecoder.decode(value.toString(), urlEncoding.name());
} catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public void setFilters(List<FilterInfo<?>> filters) {
this.filtersToApply = filters;
}
public List<FilterInfo<?>> getFilters() {
return filtersToApply;
}
public void setService(Service<MethodMeta, Action> svc) {
if(this.filtersAndMethodToCall != null)
throw new IllegalStateException("Service was already set on this RouteMeta="+this+". It should only be set once on startup");
this.filtersAndMethodToCall = svc;
}
public Service<MethodMeta, Action> getService222() {
return filtersAndMethodToCall;
}
public void setContentBinder(BodyContentBinder binder) {
this.bodyContentBinder = binder;
}
public BodyContentBinder getBodyContentBinder() {
return bodyContentBinder;
}
}