Package org.springframework.roo.addon.gwt.locator

Source Code of org.springframework.roo.addon.gwt.locator.GwtLocatorMetadataProviderImpl

package org.springframework.roo.addon.gwt.locator;

import static org.springframework.roo.addon.gwt.GwtJavaType.LOCATOR;
import static org.springframework.roo.model.JavaType.CLASS;

import java.lang.reflect.Modifier;
import java.util.Arrays;

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.osgi.service.component.ComponentContext;
import org.springframework.roo.addon.gwt.GwtTemplateService;
import org.springframework.roo.addon.gwt.GwtTypeService;
import org.springframework.roo.addon.gwt.GwtUtils;
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.customdata.CustomDataKeys;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.details.MethodMetadata;
import org.springframework.roo.classpath.details.MethodMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
import org.springframework.roo.classpath.layers.LayerService;
import org.springframework.roo.classpath.layers.LayerType;
import org.springframework.roo.classpath.layers.MemberTypeAdditions;
import org.springframework.roo.classpath.layers.MethodParameter;
import org.springframework.roo.classpath.persistence.PersistenceMemberLocator;
import org.springframework.roo.metadata.MetadataDependencyRegistry;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.metadata.MetadataItem;
import org.springframework.roo.metadata.MetadataService;
import org.springframework.roo.model.DataType;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.RooJavaType;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.ProjectOperations;

@Component(immediate = true)
@Service
public class GwtLocatorMetadataProviderImpl implements
        GwtLocatorMetadataProvider {

    private static final int LAYER_POSITION = LayerType.HIGHEST.getPosition();

    @Reference GwtTypeService gwtTypeService;
    @Reference GwtTemplateService gwtTemplateService;
    @Reference LayerService layerService;
    @Reference MetadataDependencyRegistry metadataDependencyRegistry;
    @Reference MetadataService metadataService;
    @Reference PersistenceMemberLocator persistenceMemberLocator;
    @Reference ProjectOperations projectOperations;
    @Reference TypeLocationService typeLocationService;
    @Reference TypeManagementService typeManagementService;

    protected void activate(final ComponentContext context) {
        metadataDependencyRegistry.registerDependency(
                PhysicalTypeIdentifier.getMetadataIdentiferType(),
                getProvidesType());
    }

    protected void deactivate(final ComponentContext context) {
        metadataDependencyRegistry.deregisterDependency(
                PhysicalTypeIdentifier.getMetadataIdentiferType(),
                getProvidesType());
    }

    public MetadataItem get(final String metadataIdentificationString) {
        final ClassOrInterfaceTypeDetails proxy = getGovernor(metadataIdentificationString);
        if (proxy == null) {
            return null;
        }

        final AnnotationMetadata proxyAnnotation = GwtUtils.getFirstAnnotation(
                proxy, GwtUtils.PROXY_ANNOTATIONS);
        if (proxyAnnotation == null) {
            return null;
        }

        final String locatorType = GwtUtils.getStringValue(proxyAnnotation
                .getAttribute("locator"));
        if (StringUtils.isBlank(locatorType)) {
            return null;
        }

        final ClassOrInterfaceTypeDetails entityType = gwtTypeService
                .lookupEntityFromProxy(proxy);
        if (entityType == null || Modifier.isAbstract(entityType.getModifier())) {
            return null;
        }

        boolean useXmlConfiguration = false;
        final ClassOrInterfaceTypeDetails existingLocator = gwtTypeService
                .lookupLocatorFromEntity(entityType);
        if (existingLocator != null) {
            AnnotationMetadata annotation = existingLocator
                    .getAnnotation(RooJavaType.ROO_GWT_LOCATOR);
            AnnotationAttributeValue<Boolean> attribute = annotation
                    .getAttribute("useXmlConfiguration");
            if (attribute != null)
                useXmlConfiguration = attribute.getValue();
        }

        final JavaType entity = entityType.getName();
        final MethodMetadata identifierAccessor = persistenceMemberLocator
                .getIdentifierAccessor(entity);
        final MethodMetadata versionAccessor = persistenceMemberLocator
                .getVersionAccessor(entity);
        if (identifierAccessor == null || versionAccessor == null) {
            return null;
        }

        final JavaType identifierType = GwtUtils.convertPrimitiveType(
                identifierAccessor.getReturnType(), true);
        final String locatorPhysicalTypeId = PhysicalTypeIdentifier
                .createIdentifier(new JavaType(locatorType),
                        PhysicalTypeIdentifier.getPath(proxy
                                .getDeclaredByMetadataId()));
        final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
                locatorPhysicalTypeId);
        final AnnotationMetadataBuilder annotationMetadataBuilder = new AnnotationMetadataBuilder(
                RooJavaType.ROO_GWT_LOCATOR);
        annotationMetadataBuilder.addStringAttribute("value",
                entity.getFullyQualifiedTypeName());

        if (useXmlConfiguration) {
            annotationMetadataBuilder.addBooleanAttribute(
                    "useXmlConfiguration", true);
        }
        cidBuilder.addAnnotation(annotationMetadataBuilder);

        if (!useXmlConfiguration) {
            cidBuilder.addAnnotation(new AnnotationMetadataBuilder(
                    SpringJavaType.COMPONENT));
        }
        cidBuilder.setName(new JavaType(locatorType));
        cidBuilder.setModifier(Modifier.PUBLIC);
        cidBuilder.setPhysicalTypeCategory(PhysicalTypeCategory.CLASS);
        cidBuilder.addExtendsTypes(new JavaType(LOCATOR
                .getFullyQualifiedTypeName(), 0, DataType.TYPE, null, Arrays
                .asList(entity, identifierType)));
        cidBuilder.addMethod(getCreateMethod(locatorPhysicalTypeId, entity));

        final MemberTypeAdditions findMethodAdditions = layerService
                .getMemberTypeAdditions(locatorPhysicalTypeId,
                        CustomDataKeys.FIND_METHOD.name(), entity,
                        identifierType, LAYER_POSITION, !useXmlConfiguration,
                        new MethodParameter(identifierType, "id"));

        JavaType potentialService = null;
        FieldMetadata fieldMetadata = findMethodAdditions.getInvokedField();
        if (fieldMetadata != null) {
            potentialService = fieldMetadata.getFieldType();
        }

        Validate.notNull(findMethodAdditions,
                "Find method not available for entity '%s'",
                entity.getFullyQualifiedTypeName());
        cidBuilder.addMethod(getFindMethod(findMethodAdditions, cidBuilder,
                locatorPhysicalTypeId, entity, identifierType));

        cidBuilder
                .addMethod(getDomainTypeMethod(locatorPhysicalTypeId, entity));
        cidBuilder.addMethod(getIdMethod(locatorPhysicalTypeId, entity,
                identifierAccessor));
        cidBuilder.addMethod(getIdTypeMethod(locatorPhysicalTypeId, entity,
                identifierType));
        cidBuilder.addMethod(getVersionMethod(locatorPhysicalTypeId, entity,
                versionAccessor));

        ClassOrInterfaceTypeDetails locator = cidBuilder.build();

        // Adds or removes locator from XML configuration
        if (useXmlConfiguration) {
            gwtTemplateService.addLocatorToXmlConfiguration(locator,
                    potentialService);
        }
        else {
            gwtTemplateService.removeLocatorFromXmlConfiguration(locator);
        }

        typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
        return null;
    }

    private MethodMetadataBuilder getCreateMethod(final String declaredById,
            final JavaType targetType) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return new "
                + targetType.getSimpleTypeName() + "();");
        final MethodMetadataBuilder createMethodBuilder = new MethodMetadataBuilder(
                declaredById, Modifier.PUBLIC, new JavaSymbolName("create"),
                targetType, invocableMemberBodyBuilder);
        final JavaType wildEntityType = new JavaType(
                targetType.getFullyQualifiedTypeName(), 0, DataType.VARIABLE,
                JavaType.WILDCARD_EXTENDS, null);
        final JavaType classParameterType = new JavaType(
                JavaType.CLASS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
                null, Arrays.asList(wildEntityType));
        createMethodBuilder.addParameter("clazz", classParameterType);
        return createMethodBuilder;
    }

    private MethodMetadataBuilder getDomainTypeMethod(
            final String declaredById, final JavaType targetType) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return "
                + targetType.getSimpleTypeName() + ".class;");
        final JavaType returnType = new JavaType(
                CLASS.getFullyQualifiedTypeName(), 0, DataType.TYPE, null,
                Arrays.asList(targetType));
        return new MethodMetadataBuilder(declaredById, Modifier.PUBLIC,
                new JavaSymbolName("getDomainType"), returnType,
                invocableMemberBodyBuilder);
    }

    private MethodMetadataBuilder getFindMethod(
            final MemberTypeAdditions findMethodAdditions,
            final ClassOrInterfaceTypeDetailsBuilder locatorBuilder,
            final String declaredById, final JavaType targetType,
            final JavaType idType) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return ")
                .append(findMethodAdditions.getMethodCall()).append(";");
        findMethodAdditions.copyAdditionsTo(locatorBuilder,
                locatorBuilder.build());
        final MethodMetadataBuilder findMethodBuilder = new MethodMetadataBuilder(
                declaredById, Modifier.PUBLIC, new JavaSymbolName("find"),
                targetType, invocableMemberBodyBuilder);
        final JavaType wildEntityType = new JavaType(
                targetType.getFullyQualifiedTypeName(), 0, DataType.VARIABLE,
                JavaType.WILDCARD_EXTENDS, null);
        final JavaType classParameterType = new JavaType(
                JavaType.CLASS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
                null, Arrays.asList(wildEntityType));
        findMethodBuilder.addParameter("clazz", classParameterType);
        findMethodBuilder.addParameter("id", idType);
        return findMethodBuilder;
    }

    private ClassOrInterfaceTypeDetails getGovernor(
            final String metadataIdentificationString) {
        final JavaType governorTypeName = GwtLocatorMetadata
                .getJavaType(metadataIdentificationString);
        final LogicalPath governorTypePath = GwtLocatorMetadata
                .getPath(metadataIdentificationString);
        final String physicalTypeId = PhysicalTypeIdentifier.createIdentifier(
                governorTypeName, governorTypePath);
        return typeLocationService.getTypeDetails(physicalTypeId);
    }

    private MethodMetadataBuilder getIdMethod(final String declaredById,
            final JavaType targetType, final MethodMetadata idAccessor) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return "
                + StringUtils.uncapitalize(targetType.getSimpleTypeName())
                + "." + idAccessor.getMethodName() + "();");
        final MethodMetadataBuilder getIdMethod = new MethodMetadataBuilder(
                declaredById,
                Modifier.PUBLIC,
                new JavaSymbolName("getId"),
                GwtUtils.convertPrimitiveType(idAccessor.getReturnType(), true),
                invocableMemberBodyBuilder);
        getIdMethod.addParameter(
                StringUtils.uncapitalize(targetType.getSimpleTypeName()),
                targetType);
        return getIdMethod;
    }

    private MethodMetadataBuilder getIdTypeMethod(final String declaredById,
            final JavaType targetType, final JavaType idType) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return "
                + idType.getSimpleTypeName() + ".class;");
        final JavaType returnType = new JavaType(
                JavaType.CLASS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
                null, Arrays.asList(idType));
        return new MethodMetadataBuilder(declaredById, Modifier.PUBLIC,
                new JavaSymbolName("getIdType"), returnType,
                invocableMemberBodyBuilder);
    }

    public String getProvidesType() {
        return GwtLocatorMetadata.getMetadataIdentifierType();
    }

    private MethodMetadataBuilder getVersionMethod(final String declaredById,
            final JavaType targetType, final MethodMetadata versionAccessor) {
        final InvocableMemberBodyBuilder invocableMemberBodyBuilder = InvocableMemberBodyBuilder
                .getInstance();
        invocableMemberBodyBuilder.append("return "
                + StringUtils.uncapitalize(targetType.getSimpleTypeName())
                + "." + versionAccessor.getMethodName() + "();");
        final MethodMetadataBuilder getIdMethodBuilder = new MethodMetadataBuilder(
                declaredById, Modifier.PUBLIC,
                new JavaSymbolName("getVersion"), JavaType.OBJECT,
                invocableMemberBodyBuilder);
        getIdMethodBuilder.addParameter(
                StringUtils.uncapitalize(targetType.getSimpleTypeName()),
                targetType);
        return getIdMethodBuilder;
    }

    public void notify(final String upstreamDependency,
            String downstreamDependency) {
        if (MetadataIdentificationUtils
                .isIdentifyingClass(downstreamDependency)) {
            Validate.isTrue(
                    MetadataIdentificationUtils.getMetadataClass(
                            upstreamDependency).equals(
                            MetadataIdentificationUtils
                                    .getMetadataClass(PhysicalTypeIdentifier
                                            .getMetadataIdentiferType())),
                    "Expected class-level notifications only for PhysicalTypeIdentifier (not '%s')",
                    upstreamDependency);

            final ClassOrInterfaceTypeDetails cid = typeLocationService
                    .getTypeDetails(upstreamDependency);
            if (cid == null) {
                return;
            }
            boolean processed = false;
            if (cid.getAnnotation(RooJavaType.ROO_GWT_REQUEST) != null) {
                final ClassOrInterfaceTypeDetails proxy = gwtTypeService
                        .lookupProxyFromRequest(cid);
                if (proxy != null) {
                    final JavaType typeName = PhysicalTypeIdentifier
                            .getJavaType(proxy.getDeclaredByMetadataId());
                    final LogicalPath typePath = PhysicalTypeIdentifier
                            .getPath(proxy.getDeclaredByMetadataId());
                    downstreamDependency = GwtLocatorMetadata.createIdentifier(
                            typeName, typePath);
                    processed = true;
                }
            }
            if (!processed
                    && cid.getAnnotation(RooJavaType.ROO_GWT_PROXY) == null) {
                boolean found = false;
                for (final ClassOrInterfaceTypeDetails proxyCid : typeLocationService
                        .findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_GWT_PROXY)) {
                    final AnnotationMetadata annotationMetadata = GwtUtils
                            .getFirstAnnotation(proxyCid,
                                    GwtUtils.ROO_PROXY_REQUEST_ANNOTATIONS);
                    if (annotationMetadata != null) {
                        final AnnotationAttributeValue<?> attributeValue = annotationMetadata
                                .getAttribute("value");
                        if (attributeValue != null) {
                            final String mirrorName = GwtUtils
                                    .getStringValue(attributeValue);
                            if (mirrorName != null
                                    && cid.getName()
                                            .getFullyQualifiedTypeName()
                                            .equals(attributeValue.getValue())) {
                                found = true;
                                final JavaType typeName = PhysicalTypeIdentifier
                                        .getJavaType(proxyCid
                                                .getDeclaredByMetadataId());
                                final LogicalPath typePath = PhysicalTypeIdentifier
                                        .getPath(proxyCid
                                                .getDeclaredByMetadataId());
                                downstreamDependency = GwtLocatorMetadata
                                        .createIdentifier(typeName, typePath);
                                break;
                            }
                        }
                    }
                }
                if (!found) {
                    return;
                }
            }
            else if (!processed) {
                // A physical Java type has changed, and determine what the
                // corresponding local metadata identification string would have
                // been
                final JavaType typeName = PhysicalTypeIdentifier
                        .getJavaType(upstreamDependency);
                final LogicalPath typePath = PhysicalTypeIdentifier
                        .getPath(upstreamDependency);
                downstreamDependency = GwtLocatorMetadata.createIdentifier(
                        typeName, typePath);
            }

            // We only need to proceed if the downstream dependency relationship
            // is not already registered
            // (if it's already registered, the event will be delivered directly
            // later on)
            if (metadataDependencyRegistry.getDownstream(upstreamDependency)
                    .contains(downstreamDependency)) {
                return;
            }
        }

        // We should now have an instance-specific "downstream dependency" that
        // can be processed by this class
        Validate.isTrue(
                MetadataIdentificationUtils.getMetadataClass(
                        downstreamDependency).equals(
                        MetadataIdentificationUtils
                                .getMetadataClass(getProvidesType())),
                "Unexpected downstream notification for '%s' to this provider (which uses '%s')",
                downstreamDependency, getProvidesType());

        metadataService.evictAndGet(downstreamDependency);
    }
}
TOP

Related Classes of org.springframework.roo.addon.gwt.locator.GwtLocatorMetadataProviderImpl

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.