package org.springframework.roo.addon.web.mvc.controller.addon; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.osgi.service.component.ComponentContext; import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType; import org.springframework.roo.classpath.MetadataLocatorUtils; import org.springframework.roo.classpath.TypeLocationService; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.EnumAttributeValue; import org.springframework.roo.metadata.MetadataDependencyRegistry; import org.springframework.roo.model.JavaType; import org.springframework.roo.model.RooJavaType; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * The {@link ControllerLocator} implementation. * * @author Jose Manuel Vivó * @since 2.0.0 */ @Component @Service public class ControllerLocatorImpl implements ControllerLocator { @Reference private TypeLocationService typeLocationService; @Reference private MetadataDependencyRegistry dependencyRegistry; private MetadataLocatorUtils<ControllerType> util; /** * Cache for {@link ControllerAnnotationValues} by controller javaType */ private Map<JavaType, ControllerAnnotationValues> valuesCache = new HashMap<JavaType, ControllerAnnotationValues>(30); protected void activate(final ComponentContext cContext) { util = new MetadataLocatorUtils<ControllerType>(new Evaluator()); dependencyRegistry.addNotificationListener(util); } public Collection<ClassOrInterfaceTypeDetails> getControllers(final JavaType domainType) { return util.getValue(domainType, null); } public Collection<ClassOrInterfaceTypeDetails> getControllers(final JavaType domainType, ControllerType type) { return util.getValue(domainType, type); } @Override public Collection<ClassOrInterfaceTypeDetails> getControllers(JavaType domainType, ControllerType type, JavaType viewType) { final Collection<ClassOrInterfaceTypeDetails> found = getControllers(domainType, type); if (found.isEmpty()) { return found; } Collection<ClassOrInterfaceTypeDetails> result = new HashSet<ClassOrInterfaceTypeDetails>(); for (ClassOrInterfaceTypeDetails item : found) { AnnotationMetadata annotation = item.getAnnotation(viewType); if (annotation == null) { continue; } result.add(item); } return result; } private class Evaluator implements MetadataLocatorUtils.LocatorEvaluator<ControllerType> { @Override public boolean evaluateForKey(JavaType key, ClassOrInterfaceTypeDetails valueToEvalueate, ControllerType context) { final JavaType controller = valueToEvalueate.getType(); ControllerAnnotationValues values = valuesCache.get(controller); if (values == null) { values = new ControllerAnnotationValues(valueToEvalueate); valuesCache.put(controller, values); } // Get annotation type enum value ControllerType controllerType = values.getType(); JavaType entity = values.getEntity(); if (entity.equals(key)) { if (context == null) { return true; } else { return controllerType.equals(context); } } return false; } @Override public JavaType evalueteForEvict(final String streamDependency) { if (ControllerMetadata.isValid(streamDependency)) { final JavaType controller = ControllerMetadata.getJavaType(streamDependency); if (controller != null) { valuesCache.remove(controller); return controller; } } return null; } @Override public Set<ClassOrInterfaceTypeDetails> getAllPosibilities(ControllerType context) { Set<ClassOrInterfaceTypeDetails> found = typeLocationService .findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_CONTROLLER); Set<ClassOrInterfaceTypeDetails> result = new HashSet<ClassOrInterfaceTypeDetails>(); for (ClassOrInterfaceTypeDetails item : found) { ControllerAnnotationValues values = new ControllerAnnotationValues(item); if (values.getType() == context) { result.add(item); } } return result; } } }