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

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

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 org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.JavaGeneratorUtil;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAssociationClass;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelGenerator;
import org.nuiton.eugene.models.object.ObjectModelPackage;

import java.beans.Introspector;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;




/**
 *
 * @author Benjamin Poussin - [email protected]
 * @plexus.component role="org.nuiton.eugene.Template" role-hint="org.nuiton.topia.templates.EntityHibernateMappingGenerator"
 */
public class EntityHibernateMappingGenerator extends ObjectModelGenerator {

    /**
     * Logger.
     */
    private static final Log log = LogFactory
            .getLog(EntityHibernateMappingGenerator.class);

    private static final String HIBERNATE_ATTRIBUTE_DEFAULT = "default";

    private static final String HIBERNATE_ATTRIBUTE_SQL_TYPE = "sql-type";

    private static final String HIBERNATE_ATTRIBUTE_NAME = "name";

    private Map columnNamesMap = new HashMap<>();

    public static final String HIBERNATE_ATTRIBUTE_LAZY = "lazy";

    public static final String HIBERNATE_ATTRIBUTE_FETCH = "fetch";

    public static final String HIBERNATE_ATTRIBUTE_NOT_NULL = "not-null";

    public static final String HIBERNATE_ATTRIBUTE_SCHEMA = "schema";

    public static final String HIBERNATE_ATTRIBUTE_PROXY = "proxy";

    public static final String HIBERNATE_ATTRIBUTE_INDEX = "index";

    public static final String HIBERNATE_ATTRIBUTE_UNIQUE = "unique";

    public static final String HIBERNATE_ATTRIBUTE_LENGTH = "length";

    public static final String HIBERNATE_ATTRIBUTE_ORDER_BY = "order-by";

    public static final String HIBERNATE_ATTRIBUTE_CASCADE = "cascade";

    public static final String HIBERNATE_ATTRIBUTE_INVERSE = "inverse";

    public static final String HIBERNATE_ATTRIBUTE_TABLE = "table";

    public static final String HIBERNATE_ATTRIBUTE_DISCRIMINATOR_VALUE= "discriminator-value";

    public static final String HIBERNATE_ATTRIBUTE_FOREIGN_KEY = "foreign-key";

    protected TopiaTemplateHelper templateHelper;

    protected final TopiaHibernateTagValues topiaHibernateTagValues;

    public EntityHibernateMappingGenerator() {
        this.topiaHibernateTagValues = new TopiaHibernateTagValues();
    }

    class ClassContext {

        private final ObjectModel model;

        private final ObjectModelClass input;

        private final boolean generateForeignKeyNames;

        private final String tableName;

        private final String schema;

        private ObjectModelPackage aPackage;

        ClassContext(ObjectModel model, ObjectModelPackage aPackage, ObjectModelClass input) {
            this.model = model;
            this.input = input;
            this.aPackage=aPackage;
            this.generateForeignKeyNames = topiaHibernateTagValues.isGenerateForeignKeyNames(input, model);
            this.tableName = templateHelper.getDbName(input);
            this.schema = topiaHibernateTagValues.getDbSchemaNameTagValue(input, aPackage, model);
        }

        public boolean isGenerateForeignKeyNames() {
            return generateForeignKeyNames;
        }

        public String getTableName() {
            return tableName;
        }

        public boolean isUseSchema() {
            return schema != null;
        }

        public String getSchema() {
            return schema;
        }

        public String getForeignKeyName(String attrColumn) {
            return getForeignKeyName(tableName , attrColumn).toLowerCase();
        }

        public String getForeignKeyName(String tableName, String attrColumn) {
            return ("fk_" + tableName + "_" + attrColumn).toLowerCase();
        }

        public ObjectModelClass getInput() {
            return input;
        }

        public ObjectModelPackage getPackage() {
            return aPackage;
        }
    }

    @Override
    public String getFilenameForClass(ObjectModelClass clazz) {
        if (templateHelper == null) {
            templateHelper = new TopiaTemplateHelper(model);
        }
        String DOName = templateHelper.getDOType(clazz, model);
        return DOName.replace('.', File.separatorChar) + ".hbm.xml";
    }

    @Override
    public void generateFromClass(Writer output,
                                  ObjectModelClass input) throws IOException {

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

        String persistenceType = templateHelper.getPersistenceType(input);
        if (!templateHelper.isEntity(input) &&
            templateHelper.PERSISTENCE_TYPE_HIBERNATE.equals(persistenceType)) {
            return;
        }

        if (fileFoundInClassPath(input)) {
            return;
        }

        ObjectModelPackage aPackage = model.getPackage(input);
        ClassContext classContext = new ClassContext(model, aPackage, input);

output.write("\n");
output.write("\n");
output.write("");
        boolean haveSuper = input.getSuperclasses().size() > 0;
        // la liste des attributs faisant parti de la clef metier
        List naturalAttributes = new ArrayList<>();
        // la liste des autres attributs
        List noneNaturalAttributes = new ArrayList<>();

        String clazzDOType = templateHelper.getDOType(input, model);
        String tableName = classContext.getTableName();
        String isAbstract = BooleanUtils.toStringTrueFalse(input.isAbstract());
        String clazzFQN = input.getQualifiedName();

        Map optionalAttributesMap = new HashMap<>();

        if (classContext.isUseSchema()) {
            generateFromTagValue(optionalAttributesMap,HIBERNATE_ATTRIBUTE_SCHEMA, classContext.getSchema());
        }

        //On précise au proxy de quelle interface hérite l'objet

        String proxyTagValue = topiaHibernateTagValues.getProxyInterfaceTagValue(input, aPackage, model);
        if (StringUtils.isEmpty(proxyTagValue) || !proxyTagValue.equals("none")) {
            generateFromTagValue(optionalAttributesMap,HIBERNATE_ATTRIBUTE_PROXY, clazzFQN);
        }

        String inheritanceStrategy = null;
        if (haveSuper) {
            ObjectModelClass superClass = input.getSuperclasses().iterator().next();
            String superClassname = superClass.getQualifiedName();
            if (log.isDebugEnabled()) {
            	log.debug("superClass for " + input.getQualifiedName() + " is " + superClassname);
            }
            String superClassDOType = templateHelper.getDOType(superClassname, model);
            inheritanceStrategy = templateHelper.getInheritanceStrategy(superClass);
            if ("joined-subclass".equals(inheritanceStrategy) || "union-subclass".equals(inheritanceStrategy)) {
                generateFromTagValue(optionalAttributesMap,HIBERNATE_ATTRIBUTE_TABLE, tableName);
            }
            if ("subclass".equals(inheritanceStrategy)) {
                generateFromTagValue(optionalAttributesMap,HIBERNATE_ATTRIBUTE_DISCRIMINATOR_VALUE, clazzDOType);
            }
            String optionalAttributes = attributesToString(optionalAttributesMap);
output.write("    <"+inheritanceStrategy+" name=\""+clazzDOType+"\" extends=\""+superClassDOType+"\" abstract=\""+isAbstract+"\""+optionalAttributes+">\n");
output.write("");
            if ("joined-subclass".equals(inheritanceStrategy)) {
output.write("        \n");
output.write("");
            }
            // FIXME mieux gerer le cas haveSuper
            noneNaturalAttributes.addAll(input.getAttributes());
        } else {
            String optionalAttributes = attributesToString(optionalAttributesMap);
output.write("    \n");
output.write("        \n");
output.write("");
            // cas où on defini la super class, il faut un discriminator seulement dans le cas de
            // la strategy subclass
            String currentInheritanceStrategy = templateHelper.getInheritanceStrategy(input);
            if ("subclass".equals(currentInheritanceStrategy)) {
output.write("        \n");
output.write("");
            }

            // on detecte les attributs des clef metiers            
            for (ObjectModelAttribute attr : input.getAttributes()) {
                if (topiaHibernateTagValues.getNaturalIdTagValue(attr)) {
                    // attribut metier
                    naturalAttributes.add(attr);
                } else {
                    // attribut normal
                    noneNaturalAttributes.add(attr);
                }
            }
            if (!naturalAttributes.isEmpty()) {
                // generation de la clef metier
                boolean mutable = topiaHibernateTagValues.getNaturalIdMutableTagValue(input);
                String mutableStr = mutable ? " mutable=\"true\"" : "";
                if (log.isDebugEnabled()) {
                    log.debug("natural-id detected for class " + input.getName() + " (" + mutableStr + ") attributes : " + naturalAttributes);
                }
output.write("        \n");
output.write("");
                generateAttributes(output, classContext, naturalAttributes, "    ");
output.write("        \n");
output.write("");
            }
output.write("        \n");
output.write("        \n");
output.write("");
        }

        generateAttributes(output, classContext, noneNaturalAttributes, "");

        if (haveSuper) {
output.write("    \n");
output.write("");
        } else {
output.write("    \n");
output.write("");
        }

        generateDatabaseObjects(output, classContext, naturalAttributes);
        generateDatabaseObjects(output, classContext, noneNaturalAttributes);

output.write("\n");
output.write("");
    }

    protected void generateDatabaseObjects(Writer output,
                                           ClassContext classContext,
                                           List attributes) throws IOException {

        for (ObjectModelAttribute attribute : attributes) {
            if (!attribute.isNavigable() ||
                    attribute.hasAssociationClass() ||
                    !GeneratorUtil.isNMultiplicity(attribute) ||
                    GeneratorUtil.isNMultiplicity(attribute.getReverseMaxMultiplicity()) ||
                    attribute.getClassifier() == null ||
                    !templateHelper.isEntity(attribute.getClassifier()) ||
                    templateHelper.isAbstract(attribute.getClassifier())
                    ) {

                // skip for this case (not a nm-multiplicity attribute)
                continue;
            }

            ObjectModelPackage aPackage = classContext.getPackage();

            boolean indexForeignKeys =
                    topiaHibernateTagValues.getIndexForeignKeysTagValue(attribute, aPackage, model);
            
            if (!indexForeignKeys) {

                // no index to put of the attribute.
                continue;
            }

            // add database-object to create and drop index

            String schema = topiaHibernateTagValues.getDbSchemaNameTagValue(attribute.getClassifier(), aPackage, model);
            boolean withSchema = schema != null;
            String tableName;
            String propertyName;
            // On many to many relation, the index is already generated by the other table
//            if (GeneratorUtil.isNMultiplicity(attribute.getReverseMaxMultiplicity())) {
//
//                // many to many
//                tableName = templateHelper.getManyToManyTableName(attribute);
//                propertyName = templateHelper.getReverseDbNameOnReverseAttribute(attribute);
//            } else {

                // one to many
                tableName = templateHelper.getDbName(attribute.getClassifier());
                propertyName = templateHelper.getReverseDbNameOnReverseAttribute(attribute.getReverseAttribute());
//            }

            // add schema if exist (http://nuiton.org/issues/2052)
            String indexName = "idx";
            if (withSchema) {
                indexName += '_' + schema;
            }
            indexName += '_' + tableName+ '_' + propertyName ;
            indexName = indexName.toLowerCase();
            if (withSchema) {
                tableName = schema + "." + tableName;
            }

output.write("    \n");
output.write("        CREATE INDEX "+indexName+" ON "+tableName+"("+propertyName+")\n");
output.write("        DROP INDEX "+indexName+"\n");
output.write("    \n");
output.write("");

        }
    }
    protected void generateAttributes(Writer output,
                                      ClassContext classContext,
                                      List attributes,
                                      String prefix) throws IOException {
        for (ObjectModelAttribute attr : attributes) {
            ObjectModelAttribute reverse = attr.getReverseAttribute();

            // pour les asso quoi qu'il arrive il faut les lier des 2 cotes
            // pour pouvoir supprimer en cascade l'asso lors de la suppression
            // d'un des cotes
            if (attr.isNavigable()
                || templateHelper.hasUnidirectionalRelationOnAbstractType(reverse, model)
                || attr.hasAssociationClass()) {
                if (!GeneratorUtil.isNMultiplicity(attr)) {
                    if (attr.getClassifier() != null && templateHelper.isEntity(attr.getClassifier())) {
                        if (GeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) {
                            generateHibernateManyToOne(output, classContext, attr, prefix);
                        } else {
                            generateHibernateOneToOne(output, classContext, attr, prefix);
                        }
                    } else {
                        generateHibernateProperty(output, classContext, attr, prefix);
                    }
                } else {
                    if (attr.getClassifier() != null && templateHelper.isEntity(attr.getClassifier())) {
                        if (GeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) {
                            generateHibernateManyToMany(output, classContext, attr, prefix);
                        } else {
                            generateHibernateOneToMany(output, classContext, attr, prefix);
                        }
                    } else {
                        generateHibernateMany(output, classContext, attr, prefix);
                    }
                }
            }
        }

        //Attributs pour les classes d'association
        ObjectModelClass clazz = classContext.getInput();
        ObjectModelPackage aPackage = classContext.getPackage();
        if (clazz instanceof ObjectModelAssociationClass) {
            ObjectModelAssociationClass assoc = (ObjectModelAssociationClass) clazz;
            for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) {
                if (attr != null) {

// Note(poussin) pour moi quoi qu'il arrive sur la classe d'association il faut
// un many-to-one, sinon on a des problemes.
//                    if ((!attr.getReverseAttribute().isNavigable()) || !Util.isNMultiplicity(attr.getReverseAttribute())) {
// / *{        <%=(attr.isComposite()?" cascade=\"delete\"":"")%>/>
// } */
//                    } else {
//                    String notNull = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_NOT_NULL, templateHelper.getNotNullTagValue(attr));
                    String notNull = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_NOT_NULL, "true"); // AThimel 14/03/2014 I think both assoc class participants must always be not-null
                    String attrName = getName(attr, true);
                    String attrType = getType(aPackage, clazz, attr, true);
                    String lazy = generateFromTagValue(HIBERNATE_ATTRIBUTE_LAZY, topiaHibernateTagValues.getLazyTagValue(attr));
                    String attrColumn = templateHelper.getDbName(attr);
                    String foreignKeyName = "";
                    if (classContext.isGenerateForeignKeyNames()) {
                        foreignKeyName = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_FOREIGN_KEY, classContext.getForeignKeyName(attrColumn)).trim();
                    }
output.write(""+prefix+"        \n");
output.write("");
//                    }
                    //Ne sert plus grâce à l'utilisation de la navigabilité
//                    if (!attr.getReverseAttribute().isNavigable()) {
//                        String type = templateHelper.getDOType(((ObjectModelClassifier)attr.getDeclaringElement()).getQualifiedName(), model);
//                        String name = Util.toLowerCaseFirstLetter(attr.getDeclaringElement().getName());
//                        if (log.isTraceEnabled()) {log.trace("reverse: " + type + " " + name);}
//                        if (!Util.isNMultiplicity(attr)) {
//{
//}
//                        }
//                    }
                }
            }
        }
    }

    protected String getName(ObjectModelAttribute attr) {
        return getName(attr, false);
    }

    protected String getName(ObjectModelAttribute attr, boolean isAssoc) {
        String result = Introspector.decapitalize(attr.getName());
        if (attr.hasAssociationClass() && !isAssoc) {
            result = GeneratorUtil.getAssocAttrName(attr);
        }
        return result;
    }

    protected String getType(ClassContext clazzContext, ObjectModelAttribute attr) {
        return getType(clazzContext.getPackage(), clazzContext.getInput(), attr, false);
    }

    protected String getType(ObjectModelPackage aPackage, ObjectModelClass clazz, ObjectModelAttribute attr) {
        return getType(aPackage, clazz, attr, false);
    }

    protected String getType(ObjectModelPackage aPackage, ObjectModelClass clazz, ObjectModelAttribute attr, boolean isAssoc) {
        if (attr.hasAssociationClass() && !isAssoc) {
            String type = attr.getAssociationClass().getQualifiedName();
            return templateHelper.getDOType(type, model);
        }

        String type = attr.getType();
        String attrType = topiaHibernateTagValues.getHibernateAttributeType(attr, clazz, aPackage, model);
        if (StringUtils.isNotEmpty(attrType)) {
            // tag value detected of the attribute
            type = attrType;
        } else {

            attrType = topiaHibernateTagValues.getAttributeType(attr, clazz, aPackage, model);
            if (StringUtils.isNotEmpty(attrType)) {
                // tag value detected of the attribute
                type = attrType;
            } else{

                // old code
                attrType = topiaHibernateTagValues.getTypeTagValue(attr);
                if (StringUtils.isNotEmpty(attrType)) {

                    // tag value detected of the attribute
                    if (log.isWarnEnabled()) {
                        String message = topiaHibernateTagValues.getDeprecatedAttributeTagValueMessage(clazz, attr, TopiaHibernateTagValues.Store.type.getName(), TopiaHibernateTagValues.Store.hibernateAttributeType.getName(), attrType);
                        log.warn(message);
                    }
                    type = attrType;
                } else {

                    String modelType = model.getTagValue(type);
                    if (StringUtils.isNotEmpty(modelType)) {

                        // tag value detected of the model
                        String message = topiaHibernateTagValues.getDeprecatedModelTagValueMessage(model, type, TopiaHibernateTagValues.Store.attributeType.getName() + "." + type , modelType);
                        log.warn(message);
                        //TODO tchemit 20100507 Explain What todes it do ? Dont understand the story of columnNamesMap
                        int bracketIndex = modelType.indexOf('(');
                        if (bracketIndex != -1) {
                            type = modelType.substring(0, bracketIndex);
                            int bracketEndIndex = modelType.indexOf(')', bracketIndex + 1);
                            String colmunList;
                            if (bracketEndIndex != -1) {
                                colmunList = modelType.substring(bracketIndex + 1, bracketEndIndex);
                            } else {
                                colmunList = modelType.substring(bracketIndex);
                            }
                            columnNamesMap.put(type, colmunList.split(","));
                        } else {
                            type = modelType;
                        }
                    }
                }
            }
        }

//        if (attr.hasAssociationClass() && !isAssoc) {
//            type = attr.getAssociationClass().getQualifiedName();
//        }
        return templateHelper.getDOType(type, model);
    }

    protected void generateHibernateProperty(Writer output,
                                             ClassContext classContext,
                                             ObjectModelAttribute attr,
                                             String prefix) throws IOException {
        String attrType = getType(classContext, attr);

        String accessField = "field";
        String tagValue = topiaHibernateTagValues.getAccessTagValue(attr);
        if (StringUtils.isNotEmpty(tagValue)) {
        	accessField = tagValue;
        }
        String attrName = attr.getName();
        String declaringElementDBName = templateHelper.getDbName(attr.getDeclaringElement());
        String tableName = declaringElementDBName + "_" + attrName;

        boolean attrIsEnumeration = attr.getClassifier() != null
                                 && attr.getClassifier().isEnum();

        if (attrType.trim().endsWith("[]")) {
            attrType = attrType.trim().substring(0, attrType.trim().length()-2);

            Map optionalAttributesMap = new HashMap<>();

            if (classContext.isUseSchema()) {
                generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_SCHEMA, classContext.getSchema());
            }

            if (JavaGeneratorUtil.isOrdered(attr)) {
            	String indexName = tableName + "_idx";
                generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_INDEX, indexName);
            }
            String optionalAttributes = attributesToString(optionalAttributesMap);
output.write(""+prefix+"        \n");
output.write(""+prefix+"          \n");
output.write(""+prefix+"          \n");
output.write(""+prefix+"          \n");
output.write(""+prefix+"        \n");
output.write("");
        } else {

            Map optionalAttributesMap = new HashMap<>();
            if (JavaGeneratorUtil.isOrdered(attr)) {
            	String indexName = tableName + "_idx";
                generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_INDEX, indexName);
            }

            if (EugeneCoreTagValues.isUnique(attr)) {

                generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_UNIQUE, "true");
            }
            generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_NOT_NULL, topiaHibernateTagValues.getNotNullTagValue(attr));
output.write(""+prefix+"         columnAttributes = new TreeMap<>();
            if (StringUtils.isNotEmpty(attr.getDefaultValue())) {
                //TC-20100129 with a default value we must use the column child tag

                String defaultValue = attr.getDefaultValue().trim();
                columnAttributes.put(HIBERNATE_ATTRIBUTE_DEFAULT, defaultValue);
            }
            String sqlType = topiaHibernateTagValues.getSqlTypeTagValue(attr);
            if (!StringUtils.isEmpty(sqlType)) {

                // an specific sql type was specified for the attribute, use it
                columnAttributes.put(HIBERNATE_ATTRIBUTE_SQL_TYPE, sqlType);
            }

            // add length attribute if required
            String lengthTagValue = topiaHibernateTagValues.getLengthTagValue(attr);
            if (!StringUtils.isEmpty(lengthTagValue)) {
                
                generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_LENGTH, lengthTagValue);
            }

            String optionalAttributes = attributesToString(optionalAttributesMap);

            // to know if specific column name mapping is given
            boolean noSpecifiedColumn = columnNames == null || columnNames.length == 0;

            if (noSpecifiedColumn) {
                
                String attrColumn = templateHelper.getDbName(attr);

                if (columnAttributes.isEmpty()) {

                    // simple case with no column node to generate

output.write(" column=\""+attrColumn+"\""+optionalAttributes+"");
                    if (attrIsEnumeration) {
output.write(">\n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"                "+attrType+"");

                        // if the user tuned the model to use name instead of
                        // ordinal to store the values, we must add a clause
                        boolean useEnumerationName = topiaHibernateTagValues.hasUseEnumerationNameTagValue(attr, classContext.getInput(), classContext.getPackage(), model);
                        if (useEnumerationName) {
                            String enumSQLType = String.valueOf(Types.VARCHAR);
output.write("\n");
output.write(""+prefix+"                \n");
output.write(""+prefix+"                "+enumSQLType+"");
                        }

output.write("\n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"        \n");
output.write("");
                    } else {
output.write("/>\n");
output.write("");
                    }
                } else {

                    // there is some attributes to write for the column node

                    columnAttributes.put(HIBERNATE_ATTRIBUTE_NAME, attrColumn);

                    StringBuilder columnAttributesBuilder = new StringBuilder();
                    for (Map.Entry entry : columnAttributes.entrySet()) {
                        String name = entry.getKey();
                        String value = entry.getValue();
                        columnAttributesBuilder.append(generateFromTagValue(name, value, null));
                    }
                    String columnAttributesAsString = " " + columnAttributesBuilder.toString().trim();
output.write(""+optionalAttributes+">\n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"        \n");
output.write("");
                }
            } else {
                
                // there is a colum name mapping specified, must use it
                //FIXME tchemit 2010-12-29 Really don't know how to apply columnAttributes for multi-columns...
output.write(""+optionalAttributes+">\n");
output.write("");
                for (String columnName : columnNames) {
                    columnName = attrName + "_" + columnName.trim();
output.write(""+prefix+"            \n");
output.write("");
                }
output.write(""+prefix+"        \n");
output.write("");
            }
        }
    }

    protected void generateHibernateOneToOne(Writer output,
                                             ClassContext classContext,
                                             ObjectModelAttribute attr,
                                             String prefix) throws IOException {
//      boolean accessField = hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model);
/// *{        <%=((attr.isComposite() || attr.hasAssociationClass())?" cascade=\"delete\"":"")%><%=((accessField)?" access=\"field\"":"")%> />
//} */
        
        // for hibernate many-to-one with unique="true" => one-to-one
        // but if it is one-to-zero-or-one unique contraints is violated
        // with null values
        boolean unique = GeneratorUtil.isOneMultiplicity(attr);
        generateHibernateManyToOne(output, classContext, attr, unique, prefix);

    }

    protected void generateHibernateOneToMany(Writer output,
                                              ClassContext classContext,
                                              ObjectModelAttribute attr,
                                              String prefix) throws IOException {
        boolean needsIndex = JavaGeneratorUtil.isOrdered(attr);
        boolean isInverse = attr.getReverseAttribute().isNavigable();
        isInverse |= templateHelper.hasUnidirectionalRelationOnAbstractType(attr, model);

        String attrName = getName(attr); // ???
        String attrType = getType(classContext, attr);
        String reverseAttrDBName = templateHelper.getReverseDbName(attr);
        String orderBy = generateFromTagValue(HIBERNATE_ATTRIBUTE_ORDER_BY, topiaHibernateTagValues.getOrderByTagValue(attr));

        String cascade = "";
        if (attr.isComposite() || attr.hasAssociationClass()) {
            cascade += HIBERNATE_ATTRIBUTE_CASCADE+"=\"all,delete-orphan\" ";
        }

        String lazy = generateFromTagValue(HIBERNATE_ATTRIBUTE_LAZY, topiaHibernateTagValues.getLazyTagValue(attr), "true");

        String fetch = generateFromTagValue(HIBERNATE_ATTRIBUTE_FETCH, topiaHibernateTagValues.getFetchTagValue(attr));

        String collType = templateHelper.getNMultiplicityHibernateType(attr);
        String inverse = "";
        if (isInverse) {
        	inverse = HIBERNATE_ATTRIBUTE_INVERSE+"=\"true\" ";
        }
        String foreignKeyAttribute = "";
        if (classContext.isGenerateForeignKeyNames()) {
            String columnName = templateHelper.getDbName(attr);
            foreignKeyAttribute = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_FOREIGN_KEY, classContext.getForeignKeyName(columnName)).trim();
        }
        if (needsIndex) {
output.write(""+prefix+"        <"+collType+" name=\""+attrName+"\" "+inverse+""+lazy+""+cascade+">\n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"        \n");
output.write("");
        }else {
output.write(""+prefix+"        <"+collType+" name=\""+attrName+"\" "+inverse+""+orderBy+""+fetch+""+lazy+""+cascade+">\n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"            \n");
output.write(""+prefix+"        \n");
output.write("");
        }
    }

    private String generateFromTagValue(String attributeName, String tagValue) {
		return generateFromTagValue(attributeName, tagValue, null);
	}

    private String generateFromTagValue(String attributeName, Boolean tagValue) {
        return generateFromTagValue(attributeName, tagValue == null ? null : String.valueOf(tagValue), null);
    }

    /**
     * Generate hibernate xml attribute with a final space.
     */
    private String generateFromTagValue(String attributeName, String tagValue, String defaultValue) {
		String result = "";
        if (StringUtils.isNotEmpty(tagValue)) {
            result+= attributeName + "=\"" + tagValue+"\" ";
        } else if (defaultValue != null) {
            result+= attributeName + "=\"" + defaultValue +"\" ";
        }
		return result;
	}

    private void generateFromTagValue(Map map, String attributeName, String tagValue) {
        generateFromTagValue(map, attributeName, tagValue, null);
    }

    private void generateFromTagValue(Map map,String attributeName, Boolean tagValue) {
        generateFromTagValue(map, attributeName, tagValue == null ? null : String.valueOf(tagValue), null);
    }

    private void generateFromTagValue(Map map,String attributeName, String tagValue, String defaultValue) {
        String value = null;
        if (StringUtils.isNotEmpty(tagValue)) {
            value = tagValue;

        } else if (defaultValue != null) {
            value = defaultValue;
        }
        if (value != null) {
            map.put(attributeName, "\"" + value + "\"");
        }
    }

    private String attributesToString(Map map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry entry : map.entrySet()) {
            sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue());
        }
        return sb.toString();
    }

	protected void generateHibernateMany(Writer output,
                                         ClassContext classContext,
                                         ObjectModelAttribute attr,
                                         String prefix) throws IOException {
        boolean needsIndex = JavaGeneratorUtil.isOrdered(attr);
        String attrName = getName(attr);
        String attrType = getType(classContext, attr);
        String collType = templateHelper.getNMultiplicityHibernateType(attr);
        String lazy = generateFromTagValue(HIBERNATE_ATTRIBUTE_LAZY, topiaHibernateTagValues.getLazyTagValue(attr));
        String attrColumn = templateHelper.getDbName(attr);
        String foreignKeyAttribute = "";
        String tableName = templateHelper.getManyToManyTableName(attr);
        if (classContext.isGenerateForeignKeyNames()) {
            foreignKeyAttribute = " " + HIBERNATE_ATTRIBUTE_FOREIGN_KEY + "=\"" + classContext.getTableName() + "_" + attrColumn + "\"";
        }
        boolean attrIsEnumeration = attr.getClassifier() != null
                && attr.getClassifier().isEnum();

output.write(""+prefix+"        <"+collType+" name=\""+attrName+"\" table=\""+tableName+"\" "+lazy+">\n");
output.write(""+prefix+"            \n");
output.write("");
        if (needsIndex) {
output.write(""+prefix+"            \n");
output.write("");
        }

        if (attrIsEnumeration) {
            boolean useEnumerationName = topiaHibernateTagValues.hasUseEnumerationNameTagValue(attr, classContext.getInput(), classContext.getPackage(), model);
output.write(""+prefix+"            \n");
output.write(""+prefix+"                \n");
output.write(""+prefix+"                    "+attrType+"\n");
output.write("");
            // if the user tuned the model to use name instead of
            // ordinal to store the values, we must add a clause
            if (useEnumerationName) {
                String enumSQLType = String.valueOf(Types.VARCHAR);
output.write(""+prefix+"                    \n");
output.write(""+prefix+"                    "+enumSQLType+"\n");
output.write("");
            }
output.write(""+prefix+"                \n");
output.write(""+prefix+"            \n");
output.write("");
        } else {
output.write(""+prefix+"            \n");
output.write("");
        }
output.write(""+prefix+"        \n");
output.write("");
    }

    protected void generateHibernateManyToOne(Writer output,
                                              ClassContext classContext,
                                              ObjectModelAttribute attr,
                                              String prefix) throws IOException {
        generateHibernateManyToOne(output, classContext, attr, false, prefix);
    }

    protected void generateHibernateManyToOne(Writer output,
                                              ClassContext classContext,
                                              ObjectModelAttribute attr,
                                              boolean isUnique,
                                              String prefix) throws IOException {
    	String attrName = getName(attr);
    	String attrType = getType(classContext, attr);
    	String attrColumn = templateHelper.getDbName(attr);
output.write(""+prefix+"        \n");
output.write("");
    }

    protected void generateHibernateManyToMany(Writer output,
                                               ClassContext classContext,
                                               ObjectModelAttribute attr,
                                               String prefix) throws IOException {
        // On ne met le inverse="true" uniquement pour un seul coté de la relation.
        // Dans le cas contraire, les modifications dans la relation ne seront
        // pas sauvegardées. Ceci n'est vrai que si les deux coté sont navigable
        boolean isInverse = attr.isNavigable() && attr.getReverseAttribute().isNavigable();
        //isInverse |= !Util.isFirstAttribute(attr);
        //isInverse = false; // 20070117 poussin: pour du many, jamais de inverse
        
        // Modification FD-2010-04-01 :
        // Le tagvalue "inverse" permet de spécifier qui possède le
        // inverse="true". Il est impératif de l'utiliser sur les deux
        // extrémités pour ne pas avoir de surprise.
        String inverseValue = topiaHibernateTagValues.getInverseTagValue(attr);
        if (StringUtils.isNotEmpty(inverseValue)) {
            isInverse &= Boolean.parseBoolean(inverseValue);
        // Si aucun tagvalue n'est défini, le choix est arbitraire : le
        // premier attribut dans l'ordre alphabétique sera choisi pour porter le
        // inverse="true"
        } else {
            isInverse &= GeneratorUtil.isFirstAttribute(attr);
        }

        boolean needsIndex = JavaGeneratorUtil.isOrdered(attr);
        String cascade = "";
        if (attr.isComposite() || attr.hasAssociationClass()) {
            cascade = " " + HIBERNATE_ATTRIBUTE_CASCADE + "=\"delete,delete-orphan\"";
        }

        String attrType = getType(classContext, attr);
        String attrName = getName(attr);
        String attrColumn = templateHelper.getDbName(attr);
        String lazy = generateFromTagValue(HIBERNATE_ATTRIBUTE_LAZY, topiaHibernateTagValues.getLazyTagValue(attr), "true");
        String orderBy = generateFromTagValue(HIBERNATE_ATTRIBUTE_ORDER_BY, topiaHibernateTagValues.getOrderByTagValue(attr));
        String collType = templateHelper.getNMultiplicityHibernateType(attr);
        String tableName = templateHelper.getManyToManyTableName(attr);
        String inverse = "";
        if (isInverse) {
        	inverse = HIBERNATE_ATTRIBUTE_INVERSE+"=\"true\" ";
        }
        String reverseAttrDBName = templateHelper.getReverseDbName(attr);
        Map optionalAttributesMap = new HashMap<>();
        if (classContext.isUseSchema()) {
            generateFromTagValue(optionalAttributesMap, HIBERNATE_ATTRIBUTE_SCHEMA, classContext.getSchema());
        }
        String optionalAttributes=attributesToString(optionalAttributesMap);
        String foreignKeyName = "";
        String reverseForeignKeyName = "";
        if (classContext.isGenerateForeignKeyNames()) {
            foreignKeyName = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_FOREIGN_KEY, classContext.getForeignKeyName(tableName, reverseAttrDBName)).trim();
            reverseForeignKeyName = " " + generateFromTagValue(HIBERNATE_ATTRIBUTE_FOREIGN_KEY, classContext.getForeignKeyName(tableName, attrColumn)).trim();
        }

output.write(""+prefix+"        <"+collType+" name=\""+attrName+"\" table=\""+tableName+"\" "+inverse+""+lazy+""+cascade+""+optionalAttributes+">\n");
output.write(""+prefix+"            \n");
output.write("");
        if (needsIndex) {
output.write(""+prefix+"            \n");
output.write("");
        }
output.write(""+prefix+"            \n");
output.write(""+prefix+"        \n");
output.write("");
    }

    protected boolean fileFoundInClassPath(ObjectModelClass input) {
        String fqn = templateHelper.getDOType(input, model);
        return getResourcesHelper().isFullyQualifiedNameInClassPath(fqn, ".hbm.xml");
    }

} //EntityHibernateMappingGenerator




© 2015 - 2025 Weber Informatics LLC | Privacy Policy