All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.topia.templates.EntityEnumTransformer Maven / Gradle / Ivy

The newest version!
package org.nuiton.topia.templates;

/*
 * #%L
 * ToPIA :: Templates
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2004 - 2014 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.Template;
import org.nuiton.eugene.java.ObjectModelTransformerToJava;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelEnumeration;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.eugene.models.object.xml.ObjectModelAttributeImpl;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.persistence.TopiaException;
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.EntityOperatorStore;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;





/**
 * Will generate XyzEntityEnum (where Xyz = Model name)
 *
 * @author Arnaud Thimel (Code Lutin)
 * @since 3.0
 */
@Component( role = Template.class, hint="org.nuiton.topia.templates.EntityEnumTransformer")
public class EntityEnumTransformer extends ObjectModelTransformerToJava {

    private static final Log log = LogFactory.getLog(EntityEnumTransformer.class);

    protected TopiaTemplateHelper templateHelper;

    protected final TopiaCoreTagValues topiaCoreTagValues;
    protected final TopiaHibernateTagValues topiaHibernateTagValues;

    public EntityEnumTransformer() {
        this.topiaCoreTagValues = new TopiaCoreTagValues();
        this.topiaHibernateTagValues = new TopiaHibernateTagValues();
    }

    @Override
    public void transformFromModel(ObjectModel input) {

        if (templateHelper == null) {
            templateHelper = new TopiaTemplateHelper(model);
        }

        String packageName = templateHelper.getApplicationContextPackage(this, model);

        String entityEnumName = templateHelper.getEntityEnumName(model);

        boolean generateOperator = topiaCoreTagValues.getGenerateOperatorForDAOHelperTagValue(model);

        generateEntityEnum(packageName, entityEnumName, generateOperator);

    }

    protected void generateEntityEnum(String packageName,
                                      String entityEnumName,
                                      boolean generateOperator) {

        List classes =
                templateHelper.getEntityClasses(model, true);

        ObjectModelEnumeration entityEnum;

        if (log.isDebugEnabled()) {
            log.debug("Will generate standalone " + entityEnumName +
                    " in package " + packageName);
        }
        entityEnum = createEnumeration(entityEnumName, packageName);
        addImport(entityEnum, TopiaEntity.class);
        if (generateOperator) {
            addImport(entityEnum, EntityOperatorStore.class);
        }
        addImport(entityEnum, Arrays.class);
        addImport(entityEnum, ArrayUtils.class);
        addImport(entityEnum, Modifier.class);

        // generate TopiaEntityEnum
        createEntityEnum(entityEnum,
                entityEnumName,
                generateOperator,
                classes
        );
    }

    protected void createEntityEnum(ObjectModelEnumeration entityEnum,
                                    String entityEnumName,
                                    boolean generateOperator,
                                    List classes) {

        ObjectModelAttributeImpl attr;
        ObjectModelOperation op;

        addInterface(entityEnum, TopiaEntityEnum.class);

        addImport(entityEnum, Array.class);
        if (generateOperator) {
            addImport(entityEnum, EntityOperator.class);
        }

        for (ObjectModelClass clazz : classes) {
            String clazzName = clazz.getName();

            boolean withNatural = false;
            boolean withNotNull = false;
            StringBuilder naturalIdsParams = new StringBuilder();
            StringBuilder notNullParams = new StringBuilder();

            Set naturalIdsAttributes = templateHelper.getNaturalIdAttributes(clazz);
            for (ObjectModelAttribute attribute: naturalIdsAttributes) {
                withNatural = true;
                // attribut metier
                naturalIdsParams.append(", \"").append(attribute.getName()).append("\"");
            }
            Set notNullIdsAttributes = templateHelper.getNotNullAttributes(clazz);
            for (ObjectModelAttribute attribute : notNullIdsAttributes) {
                withNotNull = true;
                // attribut not-null
                notNullParams.append(", \"").append(attribute.getName()).append("\"");
            }

            StringBuilder params = new StringBuilder(clazzName + ".class");

            ObjectModelPackage aPackage = model.getPackage(clazz);
            String dbSchema = topiaHibernateTagValues.getDbSchemaNameTagValue(clazz, aPackage, model);
            if (dbSchema == null) {
                params.append(", null");
            } else {
                params.append(", \"").append(dbSchema.toLowerCase()).append("\"");
            }

            String dbTable  = templateHelper.getDbName(clazz);
            params.append(", \"").append(dbTable.toLowerCase()).append("\"");

            if (withNotNull) {
                params.append(", new String[]{" + notNullParams.substring(2) + "}");
            } else {
                params.append(", ArrayUtils.EMPTY_STRING_ARRAY");
            }
            if (withNatural) {
                params.append(", ").append(naturalIdsParams.substring(2));
            }
            addLiteral(entityEnum, clazzName + '(' + params.toString() + ')');

            addImport(entityEnum, clazz);
        }

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "contract", "Class", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL);
        attr.setDocumentation("The contract of the entity.");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "dbSchemaName", "String", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL);
        attr.setDocumentation("The optional name of database schema of the entity (if none was filled, will be {@code null}).");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "dbTableName", "String", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL);
        attr.setDocumentation("The name of the database table for the entity.");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "implementationFQN", "String", null, ObjectModelJavaModifier.PRIVATE);
        attr.setDocumentation("The fully qualified name of the implementation of the entity.");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "implementation", "Class",null, ObjectModelJavaModifier.PRIVATE);
        attr.setDocumentation("The implementation class of the entity (will be lazy computed at runtime).");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "naturalIds", "String[]", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL);
        attr.setDocumentation("The array of property involved in the natural key of the entity.");

        attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "notNulls", "String[]", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL);
        attr.setDocumentation("The array of not null properties of the entity.");

        // constructor
        op = addConstructor(entityEnum, ObjectModelJavaModifier.PACKAGE);
        addParameter(op,"Class","contract");
        addParameter(op,"String","dbSchemaName");
        addParameter(op,"String","dbTableName");
        addParameter(op,"String[]","notNulls");
        addParameter(op,"String ...","naturalIds");
        setOperationBody(op, ""
+"\n"
+"        this.contract = contract;\n"
+"        this.dbSchemaName = dbSchemaName;\n"
+"        this.dbTableName = dbTableName;\n"
+"        this.notNulls = Arrays.copyOf(notNulls, notNulls.length);\n"
+"        this.naturalIds = naturalIds;\n"
+"        implementationFQN = contract.getName() + \"Impl\";\n"
+"    "
        );

        // getContract method
        op = addOperation(entityEnum, "getContract", "Class", ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        setOperationBody(op, ""
+"\n"
+"        return contract;\n"
+"    "
        );

        // dbSchemaName method
        op = addOperation(entityEnum, "dbSchemaName", String.class, ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class.getSimpleName());
        setOperationBody(op, ""
+"\n"
+"        return dbSchemaName;\n"
+"    "
        );

        // dbTableName method
        op = addOperation(entityEnum, "dbTableName", String.class, ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class.getSimpleName());
        setOperationBody(op, ""
+"\n"
+"        return dbTableName;\n"
+"    "
        );

        // getNaturalIds method
        op = addOperation(entityEnum, "getNaturalIds", "String[]", ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        setOperationBody(op, ""
+"\n"
+"        return naturalIds;\n"
+"    "
        );

        // isUseNaturalIds method
        op = addOperation(entityEnum, "isUseNaturalIds", "boolean", ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        setOperationBody(op, ""
+"\n"
+"        return naturalIds.length > 0;\n"
+"    "
        );

        // getNotNulls method
        op = addOperation(entityEnum, "getNotNulls", "String[]", ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        setOperationBody(op, ""
+"\n"
+"        return notNulls;\n"
+"    "
        );

        // isUseNotNulls method
        op = addOperation(entityEnum, "isUseNotNulls", "boolean", ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        setOperationBody(op, ""
+"\n"
+"        return notNulls.length > 0;\n"
+"    "
        );

        // getImplementationFQN method
        op = addOperation(entityEnum, "getImplementationFQN","String",ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum, op, Override.class);
        setOperationBody(op, ""
+"\n"
+"        return implementationFQN;\n"
+"    "
        );

        // setImplementationFQN method
        op = addOperation(entityEnum, "setImplementationFQN","void",ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        addParameter(op,"String","implementationFQN");
        if (generateOperator) {
            setOperationBody(op, ""
+"\n"
+"        this.implementationFQN = implementationFQN;\n"
+"        implementation = null;\n"
+"        // reinit the operators store\n"
+"        EntityOperatorStore.clear();\n"
+"    "
            );
        } else {
            setOperationBody(op, ""
+"\n"
+"        this.implementationFQN = implementationFQN;\n"
+"        this.implementation = null;\n"
+"    "
            );
        }

        // accept method
        op = addOperation(entityEnum, "accept","boolean",ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        addParameter(op,"Class","klass");
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+" constant = valueOf(klass);\n"
+"        boolean result = constant.getContract() == contract;\n"
+"        return result;\n"
+"    "
        );

        // getImplementation method
        op = addOperation(entityEnum, "getImplementation","Class",
                ObjectModelJavaModifier.PUBLIC);
        addAnnotation(entityEnum,op,Override.class);
        addImport(entityEnum, TopiaException.class);
        setOperationBody(op, ""
+"\n"
+"        if (implementation == null) {\n"
+"            try {\n"
+"                implementation = (Class) Class.forName(implementationFQN);\n"
+"            } catch (ClassNotFoundException e) {\n"
+"                throw new TopiaException(\"could not find class \" + implementationFQN, e);\n"
+"            }\n"
+"        }\n"
+"        return implementation;\n"
+"    "
        );

        // valueOf method
        op = addOperation(entityEnum, "valueOf", entityEnumName,
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        addParameter(op,"TopiaEntity", "entity");
        setOperationBody(op, ""
+"\n"
+"        return valueOf(entity.getClass());\n"
+"    "
        );

        // valueOf method
        op = addOperation(entityEnum, "valueOf", entityEnumName,
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        addParameter(op, "final Class", "klass");
        addImport(entityEnum, Sets.class);
        addImport(entityEnum, Set.class);
        addImport(entityEnum, List.class);
        addImport(entityEnum, ArrayList.class);
        addImport(entityEnum, Predicate.class);
        addImport(entityEnum, Iterables.class);
        addImport(entityEnum, Iterable.class);
        addImport(entityEnum, TopiaEntityHelper.class);
        setOperationBody(op, ""
+"\n"
+"        if (klass.isInterface()) {\n"
+"            return valueOf(klass.getSimpleName());\n"
+"        }\n"
+"\n"
+"        Class contractClass = TopiaEntityHelper.getContractClass("+entityEnumName+".values(), (Class) klass);\n"
+"\n"
+"        if (contractClass != null) {\n"
+"\n"
+"            return valueOf(contractClass.getSimpleName());\n"
+"        }\n"
+"\n"
+"        throw new IllegalArgumentException(\"no entity defined for the class \" + klass + \" in : \" + Arrays.toString("+entityEnumName+".values()));\n"
+"    "
        );

        // getContracts method
        op = addOperation(entityEnum, "getContracts", entityEnumName + "[]",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+"[] result = values();\n"
+"        return result;\n"
+"    "
        );

        // getContractClass method
        op = addOperation(entityEnum, "getContractClass", " Class",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        addParameter(op,"Class", "klass");
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+" constant = valueOf(klass);\n"
+"        Class result = (Class) constant.getContract();\n"
+"        return result;\n"
+"    "
        );

        // getContractClasses method
        op = addOperation(entityEnum, "getContractClasses", "Class[]",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+"[] values = values();\n"
+"        Class[] result = (Class[]) Array.newInstance(Class.class, values.length);\n"
+"        for (int i = 0; i < values.length; i++) {\n"
+"            result[i] = values[i].getContract();\n"
+"        }\n"
+"        return result;\n"
+"    "
        );

        // getContractClasses method
        op = addOperation(entityEnum, "getImplementationClass", " Class",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        addParameter(op,"Class", "klass");
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+" constant = valueOf(klass);\n"
+"        Class result = (Class) constant.getImplementation();\n"
+"        return result;\n"
+"    "
        );

        addImport(entityEnum, LinkedHashSet.class);
        // getImplementationClasses method
        op = addOperation(entityEnum, "getImplementationClasses", "Set>",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+"[] values = values();\n"
+"        Set> result = new LinkedHashSet>();\n"
+"        for (int i = 0; i < values.length; i++) {\n"
+"            result.add(values[i].getImplementation());\n"
+"        }\n"
+"        return result;\n"
+"    "
        );

        // getImplementationClassesAsString method
        op = addOperation(entityEnum, "getImplementationClassesAsString", "String",
                ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
        setOperationBody(op, ""
+"\n"
+"        StringBuilder buffer = new StringBuilder();\n"
+"        for (Class aClass : getImplementationClasses()) {\n"
+"            buffer.append(',').append(aClass.getName());\n"
+"        }\n"
+"        String result = buffer.substring(1);\n"
+"        return result;\n"
+"    "
        );

        if (generateOperator) {
            // getOperator method
            op = addOperation(entityEnum, "getOperator", " EntityOperator",
                    ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
            addParameter(op,"Class", "klass");
            setOperationBody(op, ""
+"\n"
+"        "+entityEnumName+" constant = valueOf(klass);\n"
+"        EntityOperator result = EntityOperatorStore.getOperator(constant);\n"
+"        return result;\n"
+"    "
            );
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy