public void inject(final ActionRequest actionRequest, final Targets targets) { final ActionRuntime actionRuntime = actionRequest.getActionRuntime(); final RouteChunk routeChunk = actionRuntime.getRouteChunk(); if (!routeChunk.hasMacrosOnPath()) { // no action path macros at all, just exit return; } // inject final String[] actionPath = actionRequest.getActionPathChunks(); int ndx = actionPath.length - 1; RouteChunk chunk = routeChunk; while (chunk.parent() != null) { final PathMacros pathMacros = chunk.pathMacros(); if (pathMacros != null) { injectMacros(actionPath[ndx], pathMacros, targets); } ndx--; chunk = chunk.parent(); } }
public Routes(final ActionsManager actionsManager) { this.root = new RouteChunk(this, null, StringPool.EMPTY); this.actionsManager = actionsManager; }
private ActionRuntime match(final RouteChunk chunk, final String[] path, final int ndx) { final int maxDeep = path.length - 1; if (ndx > maxDeep) { // too deep, don't go any further return null; } if (!chunk.match(path[ndx])) { // no match, continue return null; } if (ndx == maxDeep) { // end of the path if (chunk.isEndpoint()) { return chunk.value(); } return null; } // matched, scan children RouteChunk[] children = chunk.children(); if (children == null) { return null; } for (RouteChunk child : children) { ActionRuntime matched = match(child, path, ndx + 1); if (matched != null) { return matched; } } return null; }
assertNull(chunk.pathMacros()); chunk = chunk.parent(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]); assertNull(chunk.pathMacros().patterns()[0]); assertEquals("/re/user/image/{id}/{fmt}/macro2", cfg.getActionPath()); chunk = cfg.getRouteChunk(); assertNull(chunk.pathMacros()); chunk = chunk.parent(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("fmt", chunk.pathMacros().names()[0]); chunk = chunk.parent(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]); chunk = cfg.getRouteChunk(); assertNull(chunk.pathMacros()); assertEquals("POST", cfg.getActionMethod()); chunk = cfg.getRouteChunk(); assertNull(chunk.pathMacros()); chunk = chunk.parent(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]);
@Test void testMacrosDups() { WebApp webapp = new WebApp(); webapp.start(); ActionsManager actionsManager = webapp.madvocContainer().lookupComponent(ActionsManager.class); webapp.madvocContainer().lookupComponent(RootPackages.class).addRootPackageOf(this.getClass()); actionsManager.setPathMacroClass(RegExpPathMacros.class); actionsManager.registerAction(ReAction.class, "duplo2", null); actionsManager.registerAction(ReAction.class, "duplo1", null); ActionRuntime cfg = actionsManager.lookup("GET", MadvocUtil.splitPathToChunks("/re/duplo/123")); assertNotNull(cfg); assertEquals(ReAction.class, cfg.getActionClass()); assertEquals("/re/duplo/{id:^[0-9]+}", cfg.getActionPath()); RouteChunk chunk = cfg.getRouteChunk(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]); cfg = actionsManager.lookup("GET", MadvocUtil.splitPathToChunks("/re/duplo/aaa")); assertNotNull(cfg); assertEquals(ReAction.class, cfg.getActionClass()); assertEquals("/re/duplo/{sid}", cfg.getActionPath()); chunk = cfg.getRouteChunk(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("sid", chunk.pathMacros().names()[0]); assertEquals(2, actionsManager.getActionsCount()); }
/** * Registers manually created {@link ActionRuntime action runtime configurations}. * Optionally, if action path with the same name already exist, * exception will be thrown. */ public ActionRuntime registerActionRuntime(final ActionRuntime actionRuntime) { final String actionPath = actionRuntime.getActionPath(); final String method = actionRuntime.getActionMethod(); log.debug(() -> "Madvoc action: " + ifNotNull(method, m -> m + " ") + actionRuntime.getActionPath() + " => " + actionRuntime.createActionString()); final RouteChunk routeChunk = routes.registerPath(method, actionPath); if (routeChunk.value() != null) { // existing chunk if (detectDuplicatePathsEnabled) { throw new MadvocException("Duplicate action path for [" + actionRuntime + "] occupied by: [" + routeChunk.value() + "]"); } } else { actionsCount++; } routeChunk.bind(actionRuntime); // finally runtimes.put(actionRuntime.createActionString(), actionRuntime); // async check if (actionRuntime.isAsync()) { asyncMode = true; } return actionRuntime; }
public RouteChunk registerPath(String method, String path) { if (method == null) { method = ANY_METHOD; } else { method = method.toUpperCase(); } RouteChunk chunk = root.findOrCreateChild(method); if (method.equals(ANY_METHOD)) { // cache common root chunk anyMethodChunk = chunk; } path = StringUtil.cutSurrounding(path, StringPool.SLASH); String[] pathChunks = StringUtil.splitc(path, '/'); for (String pathChunk : pathChunks) { chunk = chunk.findOrCreateChild(pathChunk); } return chunk; }
private ActionRuntime lookupFrom(final RouteChunk chunk, final String[] path) { // matched, scan children RouteChunk[] children = chunk.children(); if (children == null) { return null; } for (RouteChunk child : children) { ActionRuntime matched = match(child, path, 0); if (matched != null) { return matched; } } return null; }
assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]); assertEquals("POST", cfg.getActionMethod()); chunk = cfg.getRouteChunk(); assertEquals(1, chunk.pathMacros().macrosCount()); assertEquals("id", chunk.pathMacros().names()[0]);
private ActionRuntime _lookup(String method, final String[] pathChunks) { // 1 - match method if (method != null) { method = method.toUpperCase(); RouteChunk methodChunk = root.findOrCreateChild(method); ActionRuntime actionRuntime = lookupFrom(methodChunk, pathChunks); if (actionRuntime != null) { return actionRuntime; } } // 2 - match all methods if (anyMethodChunk != null) { ActionRuntime actionRuntime = lookupFrom(anyMethodChunk, pathChunks); if (actionRuntime != null) { return actionRuntime; } } // nothing found return null; }
/** * Adds a new child to the tree. */ public RouteChunk add(final String newValue) { RouteChunk routeChunk = new RouteChunk(routes, this, newValue); if (children == null) { children = new RouteChunk[] {routeChunk}; } else { children = ArraysUtil.append(children, routeChunk); } return routeChunk; }