/* * Copyright 2013 eXo Platform SAS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package juzu.impl.plugin.router.metamodel; import juzu.Param; import juzu.Route; import juzu.impl.plugin.application.metamodel.ApplicationMetaModel; import juzu.impl.plugin.application.metamodel.ApplicationMetaModelPlugin; import juzu.impl.common.JSON; import juzu.impl.compiler.ElementHandle; import juzu.impl.compiler.ProcessingContext; import juzu.impl.plugin.controller.metamodel.HandlerMetaModel; import juzu.impl.plugin.controller.metamodel.PhaseParameterMetaModel; import juzu.impl.plugin.controller.metamodel.ControllerMetaModel; import juzu.impl.plugin.controller.metamodel.ControllersMetaModel; import juzu.impl.metamodel.AnnotationKey; import juzu.impl.metamodel.AnnotationState; import juzu.impl.plugin.controller.metamodel.ParameterMetaModel; import juzu.impl.plugin.router.ParamDescriptor; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Set; /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ public class RouterApplicationMetaModelPlugin extends ApplicationMetaModelPlugin { public RouterApplicationMetaModelPlugin() { super("router"); } @Override public Set<Class<? extends Annotation>> init(ProcessingContext env) { return Collections.<Class<? extends Annotation>>singleton(Route.class); } private RouterMetaModel getRoutes(ApplicationMetaModel metaModel, boolean create) { RouterMetaModel routes = metaModel.getChild(RouterMetaModel.KEY); if (routes == null && create) { metaModel.addChild(RouterMetaModel.KEY, routes = new RouterMetaModel()); } return routes; } @Override public void processAnnotationAdded(ApplicationMetaModel metaModel, AnnotationKey key, AnnotationState added) { if (key.getElement() instanceof ElementHandle.Method) { getRoutes(metaModel, true).annotations.put(key.getElement(), added); } } @Override public void processAnnotationRemoved(ApplicationMetaModel metaModel, AnnotationKey key, AnnotationState removed) { if (key.getElement() instanceof ElementHandle.Method) { getRoutes(metaModel, true).annotations.remove(key.getElement()); } } @Override public void postProcessEvents(ApplicationMetaModel metaModel) { RouterMetaModel router = getRoutes(metaModel, false); if (router != null) { router.routes.clear(); ControllersMetaModel controllers = metaModel.getChild(ControllersMetaModel.KEY); if (controllers != null) { for (ControllerMetaModel controller : controllers) { for (HandlerMetaModel method : controller) { AnnotationState annotation = router.annotations.get(method.getMethod()); if (annotation != null) { String path = (String)annotation.get("value"); Integer priority = (Integer)annotation.get("priority"); HashMap<String, ParamDescriptor> parameters = null; ExecutableElement exe = metaModel.processingContext.get(method.getMethod()); for (VariableElement ve : exe.getParameters()) { Param param = ve.getAnnotation(Param.class); if (param != null) { if (parameters == null) { parameters = new HashMap<String, ParamDescriptor>(); } String name = ve.getSimpleName().toString(); ParameterMetaModel a = method.parameterBy(name); if (a instanceof PhaseParameterMetaModel) { PhaseParameterMetaModel b = (PhaseParameterMetaModel)a; String pattern = param.pattern().length() == 0 ? null : param.pattern(); parameters.put(b.getMappedName(), new ParamDescriptor(pattern, param.preservePath(), param.captureGroup())); } else { throw new UnsupportedOperationException("Handle me gracefully"); } } } // // parameters String handle = method.getMethod().getMethodHandle().toString(); RouteMetaModel route = new RouteMetaModel(path, handle, priority != null ? priority : 0, parameters); router.routes.add(route); } } } } } } @Override public JSON getDescriptor(ApplicationMetaModel application) { RouterMetaModel router = getRoutes(application, false); if (router != null) { ArrayList<RouteMetaModel> list = new ArrayList<RouteMetaModel>(router.routes); Collections.sort(list, new Comparator<RouteMetaModel>() { @Override public int compare(RouteMetaModel o1, RouteMetaModel o2) { return ((Integer)o1.priority).compareTo(o2.priority); } }); return new JSON().map("routes", list); } return null; } }