Package org.springframework.roo.addon.web.mvc.controller

Source Code of org.springframework.roo.addon.web.mvc.controller.ControllerOperationsImpl

package org.springframework.roo.addon.web.mvc.controller;

import static org.springframework.roo.classpath.customdata.CustomDataKeys.PERSISTENT_TYPE;
import static org.springframework.roo.model.RooJavaType.ROO_WEB_SCAFFOLD;
import static org.springframework.roo.model.SpringJavaType.CONTROLLER;
import static org.springframework.roo.model.SpringJavaType.REQUEST_MAPPING;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.addon.plural.PluralMetadata;
import org.springframework.roo.addon.web.mvc.controller.scaffold.WebScaffoldMetadata;
import org.springframework.roo.classpath.PhysicalTypeCategory;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.ArrayAttributeValue;
import org.springframework.roo.classpath.details.annotations.BooleanAttributeValue;
import org.springframework.roo.classpath.details.annotations.ClassAttributeValue;
import org.springframework.roo.classpath.details.annotations.StringAttributeValue;
import org.springframework.roo.metadata.MetadataDependencyRegistry;
import org.springframework.roo.metadata.MetadataService;
import org.springframework.roo.model.JavaPackage;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.FeatureNames;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.PathResolver;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.support.logging.HandlerUtils;

/**
* Implementation of {@link ControllerOperations}.
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
@Service
public class ControllerOperationsImpl implements ControllerOperations {

    private static final Logger LOGGER = HandlerUtils
            .getLogger(ControllerOperationsImpl.class);
    private static final JavaSymbolName PATH = new JavaSymbolName("path");
    private static final JavaSymbolName VALUE = new JavaSymbolName("value");

    @Reference private MetadataDependencyRegistry dependencyRegistry;
    @Reference private MetadataService metadataService;
    @Reference private PathResolver pathResolver;
    @Reference private ProjectOperations projectOperations;
    @Reference private TypeLocationService typeLocationService;
    @Reference private TypeManagementService typeManagementService;
    @Reference private WebMvcOperations webMvcOperations;

    public void createAutomaticController(final JavaType controller,
            final JavaType entity, final Set<String> disallowedOperations,
            final String path) {
        Validate.notNull(controller, "Controller Java Type required");
        Validate.notNull(entity, "Entity Java Type required");
        Validate.notNull(disallowedOperations,
                "Set of disallowed operations required");
        Validate.notBlank(path, "Controller base path required");

        // Look for an existing controller mapped to this path
        final ClassOrInterfaceTypeDetails existingController = getExistingController(path);

        webMvcOperations.installConversionService(controller.getPackage());

        List<AnnotationMetadataBuilder> annotations = null;

        ClassOrInterfaceTypeDetailsBuilder cidBuilder = null;
        if (existingController == null) {
            final LogicalPath controllerPath = pathResolver
                    .getFocusedPath(Path.SRC_MAIN_JAVA);
            final String resourceIdentifier = typeLocationService
                    .getPhysicalTypeCanonicalPath(controller, controllerPath);
            final String declaredByMetadataId = PhysicalTypeIdentifier
                    .createIdentifier(controller,
                            pathResolver.getPath(resourceIdentifier));

            // Create annotation @RequestMapping("/myobject/**")
            final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
            requestMappingAttributes.add(new StringAttributeValue(VALUE, "/"
                    + path));
            annotations = new ArrayList<AnnotationMetadataBuilder>();
            annotations.add(new AnnotationMetadataBuilder(REQUEST_MAPPING,
                    requestMappingAttributes));

            // Create annotation @Controller
            final List<AnnotationAttributeValue<?>> controllerAttributes = new ArrayList<AnnotationAttributeValue<?>>();
            annotations.add(new AnnotationMetadataBuilder(CONTROLLER,
                    controllerAttributes));

            // Create annotation @RooWebScaffold(path = "/test",
            // formBackingObject = MyObject.class)
            annotations.add(getRooWebScaffoldAnnotation(entity,
                    disallowedOperations, path, PATH));
            cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
                    declaredByMetadataId, Modifier.PUBLIC, controller,
                    PhysicalTypeCategory.CLASS);
        }
        else {
            cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
                    existingController);
            annotations = cidBuilder.getAnnotations();
            if (MemberFindingUtils.getAnnotationOfType(
                    existingController.getAnnotations(), ROO_WEB_SCAFFOLD) == null) {
                annotations.add(getRooWebScaffoldAnnotation(entity,
                        disallowedOperations, path, PATH));
            }
        }
        cidBuilder.setAnnotations(annotations);
        typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
    }

    public void generateAll(final JavaPackage javaPackage) {
        for (final ClassOrInterfaceTypeDetails entityDetails : typeLocationService
                .findClassesOrInterfaceDetailsWithTag(PERSISTENT_TYPE)) {
            if (Modifier.isAbstract(entityDetails.getModifier())) {
                continue;
            }

            final JavaType entityType = entityDetails.getType();
            final LogicalPath entityPath = PhysicalTypeIdentifier
                    .getPath(entityDetails.getDeclaredByMetadataId());

            // Check to see if this persistent type has a web scaffold metadata
            // listening to it
            final String downstreamWebScaffoldMetadataId = WebScaffoldMetadata
                    .createIdentifier(entityType, entityPath);
            if (dependencyRegistry.getDownstream(
                    entityDetails.getDeclaredByMetadataId()).contains(
                    downstreamWebScaffoldMetadataId)) {
                // There is already a controller for this entity
                continue;
            }

            // To get here, there is no listening controller, so add one
            final PluralMetadata pluralMetadata = (PluralMetadata) metadataService
                    .get(PluralMetadata
                            .createIdentifier(entityType, entityPath));
            if (pluralMetadata != null) {
                final JavaType controller = new JavaType(
                        javaPackage.getFullyQualifiedPackageName() + "."
                                + entityType.getSimpleTypeName() + "Controller");
                createAutomaticController(controller, entityType,
                        new HashSet<String>(), pluralMetadata.getPlural()
                                .toLowerCase());
            }
        }
    }

    public boolean isControllerInstallationPossible() {
        return projectOperations.isFocusedProjectAvailable()
                && projectOperations
                        .isFeatureInstalledInFocusedModule(FeatureNames.MVC)
                && !projectOperations
                        .isFeatureInstalledInFocusedModule(FeatureNames.JSF);
    }

    public boolean isNewControllerAvailable() {
        return projectOperations.isFocusedProjectAvailable();
    }

    public void setup() {
        webMvcOperations.installAllWebMvcArtifacts();
    }

    /**
     * Looks for an existing controller mapped to the given path
     *
     * @param path (required)
     * @return <code>null</code> if there is no such controller
     */
    private ClassOrInterfaceTypeDetails getExistingController(final String path) {
        for (final ClassOrInterfaceTypeDetails cid : typeLocationService
                .findClassesOrInterfaceDetailsWithAnnotation(REQUEST_MAPPING)) {
            final AnnotationAttributeValue<?> attribute = MemberFindingUtils
                    .getAnnotationOfType(cid.getAnnotations(), REQUEST_MAPPING)
                    .getAttribute(VALUE);
            if (attribute instanceof ArrayAttributeValue) {
                final ArrayAttributeValue<?> mappingAttribute = (ArrayAttributeValue<?>) attribute;
                if (mappingAttribute.getValue().size() > 1) {
                    LOGGER.warning("Skipping controller '"
                            + cid.getName().getFullyQualifiedTypeName()
                            + "' as it contains more than one path");
                    continue;
                }
                else if (mappingAttribute.getValue().size() == 1) {
                    final StringAttributeValue attr = (StringAttributeValue) mappingAttribute
                            .getValue().get(0);
                    final String mapping = attr.getValue();
                    if (StringUtils.isNotBlank(mapping)
                            && mapping.equalsIgnoreCase("/" + path)) {
                        return cid;
                    }
                }
            }
            else if (attribute instanceof StringAttributeValue) {
                final StringAttributeValue mappingAttribute = (StringAttributeValue) attribute;
                if (mappingAttribute != null) {
                    final String mapping = mappingAttribute.getValue();
                    if (StringUtils.isNotBlank(mapping)
                            && mapping.equalsIgnoreCase("/" + path)) {
                        return cid;
                    }
                }
            }
        }
        return null;
    }

    private AnnotationMetadataBuilder getRooWebScaffoldAnnotation(
            final JavaType entity, final Set<String> disallowedOperations,
            final String path, final JavaSymbolName pathName) {
        final List<AnnotationAttributeValue<?>> rooWebScaffoldAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        rooWebScaffoldAttributes.add(new StringAttributeValue(pathName, path));
        rooWebScaffoldAttributes.add(new ClassAttributeValue(
                new JavaSymbolName("formBackingObject"), entity));
        for (final String operation : disallowedOperations) {
            rooWebScaffoldAttributes.add(new BooleanAttributeValue(
                    new JavaSymbolName(operation), false));
        }
        return new AnnotationMetadataBuilder(ROO_WEB_SCAFFOLD,
                rooWebScaffoldAttributes);
    }
}
TOP

Related Classes of org.springframework.roo.addon.web.mvc.controller.ControllerOperationsImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.