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

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

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

/*
 * #%L
 * ObServe Toolkit :: ToPIA Templates Extension
 * %%
 * Copyright (C) 2017 - 2018 IRD, Ultreia.io
 * %%
 * 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
 * .
 * #L%
 */

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.Writer;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.tuple.Pair;
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.models.object.ObjectModel;
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 org.nuiton.topia.persistence.metadata.TopiaMetadataEntity;
import org.nuiton.topia.persistence.metadata.TopiaMetadataModel;
import org.nuiton.topia.persistence.metadata.TopiaMetadataModelVisitor;




/**
 * Created on 03/01/16.
 *
 * @author Tony Chemit - [email protected]
 * @plexus.component role="org.nuiton.eugene.Template" role-hint="org.nuiton.topia.templates.TopiaMetadataModelGenerator"
 * @since 3.0.1
 */
public class TopiaMetadataModelGenerator extends ObjectModelGenerator {

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

    protected TopiaTemplateHelper templateHelper;

    protected TopiaHibernateTagValues topiaHibernateTagValues;
    protected EugeneCoreTagValues eugeneCoreTagValues;

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

    @Override
    public void generateFromModel(Writer output, ObjectModel input) {

        if (topiaHibernateTagValues == null) {
            topiaHibernateTagValues = new TopiaHibernateTagValues();
        }

        List entityClasses = getTemplateHelper().getEntityClasses(model, true);

        TopiaMetadataModel metadataModel = new TopiaMetadataModel();

        Multimap> oneToManyAssociationInverses = ArrayListMultimap.create();

        // Première passe pour construire toutes les entités
        for (ObjectModelClass entityClass : entityClasses) {
            buildMetadataEntity(entityClass, metadataModel, oneToManyAssociationInverses);
        }

        // On remplit désormais les oneToManyAssociationInverses
        for (TopiaMetadataEntity metadataEntity : metadataModel) {

            if (oneToManyAssociationInverses.containsKey(metadataEntity.getType())) {

                for (Pair pair: oneToManyAssociationInverses.get(metadataEntity.getType())) {
                    String typeName = pair.getRight();
                    String columnName = pair.getLeft();
                    metadataEntity.addOneToManyAssociationInverse(metadataEntity, typeName, columnName);
                }

            }
        }
        // Seconde passe pour aggréger les héritages
        for (ObjectModelClass entityClass : entityClasses) {
            TopiaMetadataEntity metadataEntity = metadataModel.getEntity(entityClass.getName());
            applyInheritance(metadataEntity, entityClass, metadataModel);
        }

        if (log.isDebugEnabled()) {
            TopiaMetadataModelVisitor.PrintVisitor visitor = new TopiaMetadataModelVisitor.PrintVisitor(true, "\n");
            metadataModel.accept(visitor);
            log.info("MetadataModel:\n" + visitor);
        }

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        gson.toJson(metadataModel, output);

    }

    @Override
    public String getFilenameForModel(ObjectModel model) {
        return getTopiaMetadataModelFilePath(model);
    }

    public String getTopiaMetadataModelFilePath(ObjectModel model) {
        String packageName = getTemplateHelper().getDefaultPackage(this);
        return (packageName + '.').replace('.', File.separatorChar) + model.getName() + "TopiaMetadataModel.json";
    }

    protected void applyInheritance(TopiaMetadataEntity metadataEntity, ObjectModelClass entityClass, TopiaMetadataModel metadataModel) {

        boolean haveSuper = entityClass.getSuperclasses().size() > 0;
        if (haveSuper) {
            ObjectModelClass superClass = entityClass.getSuperclasses().iterator().next();
            String parentName = superClass.getName();
            Optional optionalEntity = metadataModel.getOptionalEntity(parentName);
            if (optionalEntity.isPresent()) {

                TopiaMetadataEntity parentMetadataEntity = optionalEntity.get();
                parentMetadataEntity.putAll(metadataEntity);
                applyInheritance(metadataEntity, superClass, metadataModel);

            }
        }

    }

    protected TopiaMetadataEntity buildMetadataEntity(ObjectModelClass entityClass, TopiaMetadataModel metadataModel, Multimap> oneToManyAssociationInverses) {

        TopiaMetadataEntity metadataEntity;

        String entityClassName = entityClass.getName();
        Optional optionalClazz = metadataModel.getOptionalEntity(entityClassName);
        if (optionalClazz.isPresent()) {

            metadataEntity = optionalClazz.get();

        } else {

            if (isVerbose()) {
                log.info("Start " + entityClassName);
            }

            ObjectModelPackage aPackage = model.getPackage(entityClass);
            String dbSchemaName = topiaHibernateTagValues.getDbSchemaNameTagValue(entityClass, aPackage, model);
            String dbTableName = templateHelper.getDbName(entityClass);

            boolean haveSuper = entityClass.getSuperclasses().size() > 0;

            String parent = null;
            if (haveSuper) {
                ObjectModelClass superClass = entityClass.getSuperclasses().iterator().next();
                parent = superClass.getName();
            }
            metadataEntity = metadataModel.newEntity(parent, entityClassName, dbSchemaName, dbTableName);

            Collection attributes = entityClass.getAttributes();
            for (ObjectModelAttribute attr : attributes) {

                ObjectModelAttribute reverse = attr.getReverseAttribute();

                if (!attr.isNavigable()
                        && !getTemplateHelper().hasUnidirectionalRelationOnAbstractType(reverse, model)
                        && !attr.hasAssociationClass()) {
                    continue;
                }

                String name = attr.getName();
                String attrColumn = templateHelper.getDbName(attr);

                if (attr.getClassifier() == null || !getTemplateHelper().isEntity(attr.getClassifier())) {

                    String attrType = attr.getType();
                    switch (attrType) {
                        case "String":
                            attrType = "java.lang.String";
                            break;
                        case "Boolean":
                            attrType = "java.lang.Boolean";
                            break;
                        case "Byte":
                            attrType = "java.lang.Byte";
                            break;
                        case "Character":
                            attrType = "java.lang.Character";
                            break;
                        case "Short":
                            attrType = "java.lang.Short";
                            break;
                        case "Integer":
                            attrType = "java.lang.Integer";
                            break;
                        case "Long":
                            attrType = "java.lang.Long";
                            break;
                        case "Float":
                            attrType = "java.lang.Float";
                            break;
                        case "Double":
                            attrType = "java.lang.Double";
                            break;
                    }
                    metadataEntity.addProperty(name, attrType, attrColumn);
                    continue;
                }

                ObjectModelClass attributeClass = model.getClass(attr.getType());

                Optional optionalAttributeClass = metadataModel.getOptionalEntity(attributeClass.getName());

                TopiaMetadataEntity attributeClazz;
                attributeClazz = optionalAttributeClass.orElseGet(() -> buildMetadataEntity(attributeClass, metadataModel, oneToManyAssociationInverses));

                if (GeneratorUtil.isNMultiplicity(attr)) {

                    String reverseColumnName = templateHelper.getReverseDbName(attr);

                    if (GeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) {

                        // many to many
                        String tableName = templateHelper.getManyToManyTableName(attr);

                        metadataEntity.addManyToManyAssociation(attributeClazz, name, attrColumn, tableName, reverseColumnName);
                    } else {

                        // one to many
                        if (reverseColumnName == null) {
                            reverseColumnName = entityClassName.toLowerCase();
                        }

                        boolean ordered = EugeneCoreTagValues.isOrdered(attr);
                        if (ordered) {
                            String extraColumn = reverseColumnName+ "_idx";
                            if (log.isInfoEnabled()) {
                                log.info("Found ordered " + attr + " -> " + extraColumn);
                            }
                            attributeClazz.addExtraColumn(extraColumn);
                        }
                        metadataEntity.addOneToManyAssociation(attributeClazz, name, attrColumn);
                        oneToManyAssociationInverses.put(attributeClazz.getType(), Pair.of(reverseColumnName,metadataEntity.getType()));
                    }

                } else {
                    if (GeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) {

                        // many to one
                        metadataEntity.addManyToOneAssociation(attributeClazz, name, attrColumn);

                    } else {

                        // one to one
                        metadataEntity.addReversedAssociation(attributeClazz, name, attrColumn);
                    }
                }

            }
            if (isVerbose()) {
                log.info("End " + entityClassName);
            }
        }

        return metadataEntity;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy