package org.webpieces.router.impl.model;
import static org.webpieces.ctx.api.HttpMethod.GET;
import static org.webpieces.ctx.api.HttpMethod.POST;
import org.webpieces.ctx.api.HttpMethod;
import org.webpieces.router.api.routing.CrudRouteIds;
import org.webpieces.router.api.routing.MultiRoute;
import org.webpieces.router.api.routing.RouteId;
import org.webpieces.router.api.routing.Router;
import org.webpieces.router.impl.Route;
import org.webpieces.router.impl.RouteImpl;
import org.webpieces.router.impl.RouteMeta;
import org.webpieces.router.impl.UrlPath;
import org.webpieces.util.logging.Logger;
import org.webpieces.util.logging.LoggerFactory;
public abstract class AbstractRouteBuilder implements Router {
private static final Logger log = LoggerFactory.getLogger(AbstractRouteBuilder.class);
public static ThreadLocal<RouteModuleInfo> currentPackage = new ThreadLocal<>();
protected L3PrefixedRouting routes;
protected RouterInfo routerInfo;
protected LogicHolder holder;
protected boolean isHttpsOnlyRoutes;
public AbstractRouteBuilder(RouterInfo routerInfo, L3PrefixedRouting routes, LogicHolder holder, boolean isHttpsOnlyRoutes) {
this.routerInfo = routerInfo;
this.routes = routes;
this.holder = holder;
this.isHttpsOnlyRoutes = isHttpsOnlyRoutes;
}
@Override
public Router getScopedRouter(String path, boolean isHttpsOnlyRoutes) {
L3PrefixedRouting router = routes;
if(path != null) {
if(path.length() <= 1)
throw new IllegalArgumentException("path must be non-null and size greater than 1");
else if(!path.startsWith("/"))
throw new IllegalArgumentException("path must start with /");
else if(path.endsWith("/"))
throw new IllegalArgumentException("path must not end with /");
router = routes.getScopedRouter(path);
} else
path = "";
RouterInfo info = new RouterInfo(routerInfo.getDomain(), routerInfo.getPath()+path);
return new R3PrefixRouterBuilder(info, router, holder, isHttpsOnlyRoutes);
}
public void addRoute(Route r, RouteId routeId) {
log.info("scope:'"+routerInfo+"' adding route="+r.getMethod()+" "+r.getFullPath()+" method="+r.getControllerMethodString());
RouteMeta meta = new RouteMeta(r, holder.getInjector(), currentPackage.get(), holder.getUrlEncoding());
holder.getFinder().loadControllerIntoMetaObject(meta, true);
routes.addRoute(meta);
if(routeId != null)
holder.getReverseRoutes().addRoute(routeId, meta);
else {
holder.getReverseRoutes().addContentRoute(meta);
}
}
@Override
public void addRoute(HttpMethod method, String path, String controllerMethod, RouteId routeId) {
boolean checkSecureToken = false;
if(method == HttpMethod.POST)
checkSecureToken = true;
addRoute(method, path, controllerMethod, routeId, checkSecureToken);
}
@Override
public void addRoute(HttpMethod method, String path, String controllerMethod, RouteId routeId, boolean checkToken) {
UrlPath p = new UrlPath(routerInfo, path);
Route route = new RouteImpl(method, p, controllerMethod, routeId, isHttpsOnlyRoutes, checkToken);
addRoute(route, routeId);
}
public void addContentRoute(HttpMethod method, String path, String controllerMethod) {
UrlPath p = new UrlPath(routerInfo, path);
Route route = new RouteImpl(method, p, controllerMethod, isHttpsOnlyRoutes);
addRoute(route, null);
}
public MultiRoute addMultiRoute(HttpMethod method, String path) {
throw new UnsupportedOperationException("Not supported yet");
}
/*
* Adds routes like the following all in one method
*
* //addRoute(GET , "/user/list", "crud/CrudUserController.userList", listRoute);
* //addRoute(GET , "/user/new", "crud/CrudUserController.userAddEdit", addRoute);
* //addRoute(GET , "/user/edit/{id}", "crud/CrudUserController.userAddEdit", editRoute);
* //addRoute(POST, "/user/post", "crud/CrudUserController.postSaveUser", saveRoute);
* //addRoute(GET, "/user/delete/{id}", "crud/CrudUserController.postDeleteUser", deleteRoute);
*/
@Override
public void addCrud(String entity, String controller, CrudRouteIds routeIds) {
RouteId listRoute = routeIds.getListRoute();
RouteId addRoute = routeIds.getAddRoute();
RouteId editRoute = routeIds.getEditRoute();
RouteId postSaveRoute = routeIds.getPostSaveRoute();
RouteId confirmDelete = routeIds.getConfirmDelete();
RouteId postDeleteRoute = routeIds.getPostDeleteRoute();
String entityWithCapital = entity.substring(0, 1).toUpperCase() + entity.substring(1);
addRoute(GET , "/"+entity+"/list", controller+"."+entity+"List", listRoute);
addRoute(GET , "/"+entity+"/new", controller+"."+entity+"AddEdit", addRoute);
addRoute(GET , "/"+entity+"/edit/{id}", controller+"."+entity+"AddEdit", editRoute);
addRoute(POST, "/"+entity+"/post", controller+".postSave"+entityWithCapital, postSaveRoute);
//get the confirm delete page
addRoute(GET, "/"+entity+"/confirmdelete/{id}", controller+".confirmDelete"+entityWithCapital, confirmDelete);
//NOTE: Browsers don't support DELETE. POST might make more sense here for delete but GET is way way less html
//code(ok, 1 line instead of 3). There are hacks with javascript to support DELETE but seriously, we should just
//KISS and YAGNI (google that if you don't know).
//HOWEVER, If you don't like this, copy and paste this method and modify to be a POST OR DELETE and add the
//javascript for next time
addRoute(POST, "/"+entity+"/delete/{id}", controller+".postDelete"+entityWithCapital, postDeleteRoute);
}
}