org.gvnix.web.screen.roo.addon.AbstractPatternMetadataProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.gvnix.web.screen.roo.addon.AbstractPatternMetadataProvider.java

Source

/*
 * gvNIX. Spring Roo based RAD tool for Conselleria d'Infraestructures i
 * Transport - Generalitat Valenciana Copyright (C) 2010, 2011 CIT - Generalitat
 * Valenciana
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.gvnix.web.screen.roo.addon;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang3.Validate;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.addon.web.mvc.controller.details.DateTimeFormatDetails;
import org.springframework.roo.addon.web.mvc.controller.details.JavaTypeMetadataDetails;
import org.springframework.roo.addon.web.mvc.controller.details.WebMetadataService;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.customdata.CustomDataKeys;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.MemberHoldingTypeDetails;
import org.springframework.roo.classpath.itd.AbstractMemberDiscoveringItdMetadataProvider;
import org.springframework.roo.classpath.itd.ItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.classpath.scanner.MemberDetails;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;

/**
 * Provides {@link PatternMetadata}. This type is called by Roo to retrieve the
 * metadata for this add-on. Use this type to reference external types and
 * services needed by the metadata type. Register metadata triggers and
 * dependencies here. Also define the unique add-on ITD identifier.
 * 
 * @author Oscar Rovira (orovira at disid dot com) at <a
 *         href="http://www.disid.com">DiSiD Technologies S.L.</a> made for <a
 *         href="http://www.cit.gva.es">Conselleria d'Infraestructures i
 *         Transport</a>
 * @author Mario Martnez (mmartinez at disid dot com) at <a
 *         href="http://www.disid.com">DiSiD Technologies S.L.</a> made for <a
 *         href="http://www.cit.gva.es">Conselleria d'Infraestructures i
 *         Transport</a>
 * @since 0.8
 */
public abstract class AbstractPatternMetadataProvider extends AbstractMemberDiscoveringItdMetadataProvider {

    /** {@link RooWebScaffold} java type */
    protected static final JavaType ROOWEBSCAFFOLD_ANNOTATION = new JavaType(RooWebScaffold.class.getName());

    protected PatternService _patternService;

    /**
     * The activate method for this OSGi component, this will be called by the
     * OSGi container upon bundle activation (result of the 'addon install'
     * command)
     * 
     * @param context the component context can be used to get access to the
     *        OSGi container (ie find out if certain bundles are active)
     */
    protected abstract void activate(ComponentContext context);

    /**
     * The deactivate method for this OSGi component, this will be called by the
     * OSGi container upon bundle deactivation (result of the 'addon uninstall'
     * command)
     * 
     * @param context the component context can be used to get access to the
     *        OSGi container (ie find out if certain bundles are active)
     */
    protected abstract void deactivate(ComponentContext context);

    /**
     * Return an instance of the Metadata offered by this add-on
     */
    @Override
    protected abstract ItdTypeDetailsProvidingMetadataItem getMetadata(String mid, JavaType aspect,
            PhysicalTypeMetadata controller, String file);

    /**
     * Read the values of GvNIXRelationsPattern and for each field defined as
     * relation retrieve its java type details.
     * <p>
     * It parses the value of the GvNIXRelationsPattern annotation.
     * GvNIXRelationsPattern example:
     * </p>
     * <code>{ "PatternName1: field1=tabular, field2=register", "PatternName2: field3=tabular_edit_register" }</code>
     * 
     * @param mid Metadata identification string
     * @param controller Controller physical type metadata
     * @param entity Entity java type
     * @param webMetadataService Web metadata service
     * @return Map with java types and java type details
     */
    protected SortedMap<JavaType, JavaTypeMetadataDetails> getRelationFieldsDetails(String mid,
            PhysicalTypeMetadata controller, JavaType entity, WebMetadataService webMetadataService) {

        SortedMap<JavaType, JavaTypeMetadataDetails> relatedApplicationTypeMetadata = new TreeMap<JavaType, JavaTypeMetadataDetails>();

        // For each eligible field: put all java types details in the same map
        List<JavaType> relations = getRelationFields(mid, controller, entity, webMetadataService);
        for (JavaType relation : relations) {

            SortedMap<JavaType, JavaTypeMetadataDetails> tmp = getFieldJavaTypesDetails(relation, mid,
                    webMetadataService);
            if (tmp != null) {

                relatedApplicationTypeMetadata.putAll(tmp);
            }
        }

        return relatedApplicationTypeMetadata;
    }

    /**
     * Read the values of GvNIXRelationsPattern and for each field defined as
     * relation retrieve its java type.
     * 
     * @param mid Metadata identification string
     * @param controller Controller physical type metadata
     * @param entity Entity java type
     * @param webMetadataService Web metadata service
     * @return Map with java types and java type details
     */
    private List<JavaType> getRelationFields(String mid, PhysicalTypeMetadata controller, JavaType entity,
            WebMetadataService webMetadataService) {

        // Fields name defined into relations pattern annotation
        List<String> relations = _patternService.getControllerRelationsPatternsFields(controller);

        // Get each relation java type from eligible scaffolding fields
        List<FieldMetadata> scaffoldFields = getScaffoldEligibleFields(entity, mid, webMetadataService);

        // We're interested only in those types defined in GvNIXRelationsPattern
        // values
        List<JavaType> validFields = new ArrayList<JavaType>();
        for (FieldMetadata scaffoldEligibleField : scaffoldFields) {

            // This scaffold eligible field is defined into relations pattern
            // annotation: is a valid field
            if (relations.contains(scaffoldEligibleField.getFieldName().getSymbolName())) {

                // Get valid field type (simple or collection)
                JavaType validField = scaffoldEligibleField.getFieldType();
                if (validField.isCommonCollectionType() && !validField.getParameters().isEmpty()) {

                    validField = validField.getParameters().get(0);
                }

                validFields.add(validField);
            }
        }

        return validFields;
    }

    /**
     * For the given type returns a Map with its related application types
     * metadata.
     * 
     * @param type Field java type
     * @param mid Metadata identification string
     * @param webMetadataService Web metadata service
     * @return Map with java type and java details related to field
     */
    private SortedMap<JavaType, JavaTypeMetadataDetails> getFieldJavaTypesDetails(JavaType type, String mid,
            WebMetadataService webMetadataService) {

        // Get field metadata, field details and field persistent details
        PhysicalTypeMetadata typeMetadata = (PhysicalTypeMetadata) getMetadataService().get(
                PhysicalTypeIdentifier.createIdentifier(type, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")));
        Validate.notNull(typeMetadata,
                "Unable to obtain physical type metadata for type " + type.getFullyQualifiedTypeName());
        MemberDetails typeDetails = getMemberDetails(typeMetadata);
        MemberHoldingTypeDetails typePersistentDetails = MemberFindingUtils
                .getMostConcreteMemberHoldingTypeDetailsWithTag(typeDetails, CustomDataKeys.PERSISTENT_TYPE);

        // Get field related application type metadata if field persistent
        // details no null
        SortedMap<JavaType, JavaTypeMetadataDetails> typeRelatedApplicationTypeMetadata = webMetadataService
                .getRelatedApplicationTypeMetadata(type, typeDetails, mid);
        if (typePersistentDetails == null || typeRelatedApplicationTypeMetadata == null) {

            return null;
        }

        return typeRelatedApplicationTypeMetadata;
    }

    /**
     * Get scaffold eligible fields metadata from entity with some mid through
     * web metadata service.
     * 
     * @param entity Entity java type
     * @param mid Metadata identification string
     * @param webMetadataService Web metadata service
     * @return Entity scaffold eligible fields
     */
    private List<FieldMetadata> getScaffoldEligibleFields(JavaType entity, String mid,
            WebMetadataService webMetadataService) {

        return webMetadataService.getScaffoldEligibleFieldMetadata(entity,
                webMetadataService.getMemberDetails(entity), mid);
    }

    /**
     * Returns a map with Related entities JavaType as key, and their Map of the
     * Fields-DateTimeFormatDetails as value.
     * <p>
     * We need this data in order to register the right DateTimeFormatPattern of
     * the related entities in a master/detail pattern.
     * 
     * @param mid
     * @param controller
     * @param entity
     * @param webMetadataService
     * @return
     */
    protected Map<JavaType, Map<JavaSymbolName, DateTimeFormatDetails>> getRelationFieldsDateFormat(String mid,
            PhysicalTypeMetadata controller, JavaType entity, WebMetadataService webMetadataService) {

        // We're interested only in those types defined in GvNIXRelationsPattern
        // values
        Map<JavaType, Map<JavaSymbolName, DateTimeFormatDetails>> relatedTypesDatePatterns = new LinkedHashMap<JavaType, Map<JavaSymbolName, DateTimeFormatDetails>>();

        List<JavaType> validFields = getRelationFields(mid, controller, entity, webMetadataService);
        for (JavaType validField : validFields) {
            relatedTypesDatePatterns.put(validField, webMetadataService.getDatePatterns(validField,
                    webMetadataService.getMemberDetails(validField), mid));
        }

        return relatedTypesDatePatterns;
    }

    /**
     * Define the unique ITD file name extension
     */
    public abstract String getItdUniquenessFilenameSuffix();

    @Override
    protected abstract String getGovernorPhysicalTypeIdentifier(String mid);

    @Override
    protected abstract String createLocalIdentifier(JavaType javaType, LogicalPath path);

    public abstract String getProvidesType();

}