/** * Build a runtime model. * * @param subResourceMode if {@code true}, all resources will be processed as sub-resources. * @return runtime request routing root. */ public Router buildModel(boolean subResourceMode) { final PushMatchedUriRouter uriPushingRouter = locator.createAndInitialize(PushMatchedUriRouter.class); RouteToPathBuilder<PathPattern> lastRoutedBuilder = null; // route resource method acceptors if (!rootAcceptors.isEmpty()) { for (Map.Entry<PathPattern, List<MethodAcceptorPair>> entry : rootAcceptors.entrySet()) { final PathPattern closedResourcePathPattern = entry.getKey(); List<MethodAcceptorPair> methodAcceptorPairs = entry.getValue(); lastRoutedBuilder = routeMethodAcceptor( lastRoutedBuilder, closedResourcePathPattern, uriPushingRouter, methodSelectingAcceptorBuilder.build(workers, methodAcceptorPairs), subResourceMode); } rootAcceptors.clear(); } // route sub-resource method and locator acceptors if (!subResourceAcceptors.isEmpty()) { for (Map.Entry<PathPattern, TreeMap<PathPattern, List<MethodAcceptorPair>>> singleResourcePathEntry : subResourceAcceptors.entrySet()) { RouteToPathBuilder<PathPattern> srRoutedBuilder = null; for (Map.Entry<PathPattern, List<MethodAcceptorPair>> singlePathEntry : singleResourcePathEntry.getValue().entrySet()) { // there can be multiple sub-resource methods on the same path // but only a single sub-resource locator. List<MethodAcceptorPair> resourceMethods = Lists.newLinkedList(); MethodAcceptorPair resourceLocator = null; for (MethodAcceptorPair methodAcceptorPair : singlePathEntry.getValue()) { if (methodAcceptorPair.model.getType() == ResourceMethod.JaxrsType.RESOURCE_METHOD) { resourceMethods.add(methodAcceptorPair); } else { resourceLocator = methodAcceptorPair; } } if (!resourceMethods.isEmpty()) { final PathPattern subResourceMethodPath = PathPattern.asClosed(singlePathEntry.getKey()); srRoutedBuilder = routedBuilder(srRoutedBuilder) .route(subResourceMethodPath) .to(uriPushingRouter) .to(methodSelectingAcceptorBuilder.build(workers, resourceMethods)); } if (resourceLocator != null) { srRoutedBuilder = routedBuilder(srRoutedBuilder) .route(singlePathEntry.getKey()) .to(uriPushingRouter) .to(resourceLocator.router); } } assert srRoutedBuilder != null; lastRoutedBuilder = routeMethodAcceptor( lastRoutedBuilder, singleResourcePathEntry.getKey(), uriPushingRouter, srRoutedBuilder.build(), subResourceMode); } subResourceAcceptors.clear(); } return createRootTreeAcceptor(lastRoutedBuilder, subResourceMode); }
/** * Process a single resource model and add it to the currently build runtime routing and accepting * model. * * @param resource resource model to be processed. * @param subResourceMode if {@code true}, all resources will be processed as sub-resources. */ public void process(final Resource resource, final boolean subResourceMode) { if (!(resource.isRootResource() || subResourceMode)) { // ignore sub-resources if not in a sub-resource modelling mode. return; } // prepare & add resource method acceptors if (!resource.getResourceMethods().isEmpty()) { final PathPattern closedResourcePathPattern = (subResourceMode) ? PathPattern.END_OF_PATH_PATTERN : PathPattern.asClosed(resource.getPathPattern()); List<MethodAcceptorPair> sameResourcePathList = getAcceptorList(rootAcceptors, closedResourcePathPattern); sameResourcePathList.addAll( Lists.transform( resource.getResourceMethods(), new Function<ResourceMethod, MethodAcceptorPair>() { @Override public MethodAcceptorPair apply(ResourceMethod methodModel) { return new MethodAcceptorPair( methodModel, resource, createSingleMethodAcceptor(methodModel, subResourceMode)); } })); } final ResourceMethod resourceLocator = resource.getResourceLocator(); if (resourceLocator != null) { TreeMap<PathPattern, List<MethodAcceptorPair>> sameResourcePathMap = getPatternAcceptorListMap(resource.getPathPattern()); List<MethodAcceptorPair> locatorList = getAcceptorList(sameResourcePathMap, PathPattern.OPEN_ROOT_PATH_PATTERN); locatorList.add( new MethodAcceptorPair( resourceLocator, resource, createSingleMethodAcceptor(resourceLocator, subResourceMode))); } // prepare & add sub-resource method and locator acceptors. if (resource.getChildResources().size() > 0) { final PathPattern resourcePath = (subResourceMode) ? PathPattern.OPEN_ROOT_PATH_PATTERN : resource.getPathPattern(); TreeMap<PathPattern, List<MethodAcceptorPair>> sameResourcePathMap = getPatternAcceptorListMap(resourcePath); for (Resource child : resource.getChildResources()) { PathPattern childRelativePath = new PathPattern(child.getPath()); List<MethodAcceptorPair> samePathMethodAcceptorPairs = getAcceptorList(sameResourcePathMap, childRelativePath); for (ResourceMethod resourceMethod : child.getAllMethods()) { samePathMethodAcceptorPairs.add( new MethodAcceptorPair( resourceMethod, resource, createSingleMethodAcceptor(resourceMethod, subResourceMode))); } } } }