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

fr.ird.observe.toolkit.eugene.templates.EntityReferenceTransformer Maven / Gradle / Ivy

There is a newer version: 4.21
Show newest version
package fr.ird.observe.toolkit.eugene.templates;

/*
 * #%L
 * ObServe Toolkit :: Eugene Templates Extension
 * %%
 * Copyright (C) 2017 - 2019 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.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import fr.ird.observe.binder.EntityReferenceBinderSupport;
import fr.ird.observe.binder.data.DataDtoReferenceBinder;
import fr.ird.observe.binder.data.DataEntityReferenceBinderSupport;
import fr.ird.observe.binder.referential.ReferentialDtoReferenceBinder;
import fr.ird.observe.binder.referential.ReferentialEntityReferenceBinderSupport;
import fr.ird.observe.dto.IdDto;
import fr.ird.observe.dto.data.DataDto;
import fr.ird.observe.dto.reference.DataDtoReference;
import fr.ird.observe.dto.reference.DtoReference;
import fr.ird.observe.dto.reference.DtoReferenceDefinition;
import fr.ird.observe.dto.reference.ReferentialDtoReference;
import fr.ird.observe.dto.referential.ReferentialDto;
import fr.ird.observe.dto.referential.ReferentialLocale;
import fr.ird.observe.spi.initializer.EntitiesBinderInitializerSupport;
import org.apache.commons.lang3.StringUtils;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.java.BeanTransformer;
import org.nuiton.eugene.java.BeanTransformerContext;
import org.nuiton.eugene.java.BeanTransformerTagValues;
import org.nuiton.eugene.java.EugeneJavaTagValues;
import org.nuiton.eugene.java.JavaGeneratorUtil;
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.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;

import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;

import static fr.ird.observe.toolkit.eugene.templates.DtoReferenceTransformer.generateMetaInfService;

/**
 * Generates a reference of a bean.
 * 

* For example: *

 *     GeneratedBoatReference
 *     BoatReference
 * 
* * @author Tony Chemit - [email protected] * @plexus.component role="org.nuiton.eugene.Template" role-hint="fr.ird.observe.toolkit.eugene.templates.EntityReferenceTransformer" * @since 1.04 */ public class EntityReferenceTransformer extends ObjectModelTransformerToJava { private final EugeneCoreTagValues coreTagValues; private final EugeneJavaTagValues javaTemplatesTagValues; private final ObserveTagValues observeTagValues; private final BeanTransformerTagValues beanTagValues; private BeanTransformerContext context; public EntityReferenceTransformer() { coreTagValues = new EugeneCoreTagValues(); javaTemplatesTagValues = new EugeneJavaTagValues(); beanTagValues = new BeanTransformerTagValues(); observeTagValues = new ObserveTagValues(); } @Override public void transformFromModel(ObjectModel model) { super.transformFromModel(model); ImmutableSet.Builder withReferencesBuilder = ImmutableSet.builder(); ImmutableSet.Builder withFormBuilder = ImmutableSet.builder(); context = new BeanTransformerContext(model, coreTagValues, javaTemplatesTagValues, beanTagValues, false, false, input -> { ObjectModelPackage aPackage = model.getPackage(input.getPackageName()); boolean referential = BinderHelper.isReferentialFromPackageName(aPackage.getName()); String referencesTagValue = observeTagValues.getReferencesTagValue(input); String formTagValue = observeTagValues.getFormTagValue(input, getModel().getPackage(input.getPackageName())).trim(); boolean withReference = referencesTagValue != null || referential; boolean withForm = StringUtils.isNotEmpty(formTagValue); boolean keep = false; if (withForm) { withFormBuilder.add(input.getQualifiedName()); keep = true; } if (withReference) { withReferencesBuilder.add(input.getQualifiedName()); keep = true; } return keep; }, getLog()); context.report(); ImmutableSet withReferenceFqns = withReferencesBuilder.build(); ImmutableSet withFormFqns = withFormBuilder.build(); boolean useRelativeName = context.useRelativeName; String binderPackageName = EntityReferenceBinderSupport.class.getPackage().getName(); ObjectModelPackage defaultPackage = getModel().getPackage(getDefaultPackageName()); String packageName = defaultPackage.getName() + "."; int defaultPackageNameLength = packageName.length(); for (ObjectModelClass input : context.selectedClasses) { if (!withReferenceFqns.contains(input.getQualifiedName())) { continue; } ObjectModelPackage aPackage = getPackage(input); boolean referential = BinderHelper.isReferentialFromPackageName(aPackage.getName()); String referencesTagValue = observeTagValues.getReferencesTagValue(input); if (referencesTagValue == null && referential) { referencesTagValue = "code,label,uri"; } Objects.requireNonNull(referencesTagValue); withReferencesBuilder.add(input.getQualifiedName()); Set availableProperties = new LinkedHashSet<>(Arrays.asList(referencesTagValue.split(","))); Map binderProperties = DtoReferenceTransformer.getBinderProperties(context.selectedClassesFqn, input, availableProperties, this::getAttributeType); String prefix = getConstantPrefix(input); setConstantPrefix(prefix); String entityName = input.getName(); String dtoName = context.classesNameTranslation.get(input); String className = BinderHelper.cleanId(dtoName) + "Reference"; Class binderSuperClass = referential ? ReferentialEntityReferenceBinderSupport.class : DataEntityReferenceBinderSupport.class; String binderName = BinderHelper.generateBinderName(binderPackageName, aPackage.getName() + "." + entityName, entityName + "EntityReference"); boolean generateBinder = !getResourcesHelper().isJavaFileInClassPath(binderName); if (generateBinder) { generateBinderClass(input, useRelativeName, dtoName, className, binderName, String.format("%s<%s, %s, %s>", binderSuperClass.getName(), dtoName, className, entityName), binderProperties); } } String initializerName = "EntityBindersInitializer"; String generatedInitializerName = "Generated" + initializerName; String initializerPackageName = EntitiesBinderInitializerSupport.class.getPackage().getName(); ObjectModelPackage aPackage = getModel().getPackage(getDefaultPackageName()); generateGeneratedInitializer(initializerPackageName, aPackage.getName(), binderPackageName, generatedInitializerName, withReferenceFqns, withFormFqns); boolean generateInitializer = notFoundInClassPath(binderPackageName, initializerName); if (generateInitializer) { generateInitializer(initializerPackageName, generatedInitializerName, initializerName); } generateMetaInfService(getConfiguration(), initializerPackageName + "." + initializerName, EntitiesBinderInitializerSupport.class); } private void generateGeneratedInitializer(String initializerPackageName, String defaultPackageName, String binderPackageName, String generatedInitializerName, ImmutableSet withReferenceFqns, ImmutableSet withFormFqns) { int defaultPackageNameLength = defaultPackageName.length(); String modelName = getModel().getName(); ObjectModelClass output = createAbstractClass(generatedInitializerName, initializerPackageName); setSuperClass(output, EntitiesBinderInitializerSupport.class); addImport(output, Map.class); addImport(output, ImmutableMap.class); addImport(output, ImmutableSet.class); addImport(output, Set.class); addImport(output, LinkedHashSet.class); addImport(output, TreeMap.class); addImport(output, ReferentialDto.class); addImport(output, DataDto.class); addImport(output, IdDto.class); addImport(output, DtoReference.class); addImport(output, ReferentialDtoReference.class); addImport(output, DataDtoReference.class); addImport(output, DtoReferenceDefinition.class); addImport(output, ReferentialDtoReferenceBinder.class); addImport(output, DataDtoReferenceBinder.class); addImport(output, defaultPackageName + "." + modelName + "ModelInitializer"); addImport(output, defaultPackageName + "." + modelName + "ModelInitializerRunner"); addInterface(output, modelName + "ModelInitializer"); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC); setOperationBody(constructor, ""+"\n" +" "+modelName+"ModelInitializerRunner.init(this);\n" +" " ); ObjectModelOperation startMethod = addOperation(output, "start", "void", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, startMethod, Override.class); ObjectModelOperation endMethod = addOperation(output, "end", "void", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, endMethod, Override.class); setOperationBody(endMethod, ""+"\n" +" super.end();\n" +" " ); boolean useRelativeName = context.useRelativeName; String[] relativeNameExcludes = context.relativeNameExcludes; for (String fqn : context.selectedClassesFqn) { ObjectModelClass beanClass = context.selectedClassesByFqn.get(fqn); ObjectModelPackage thisPackage = getModel().getPackage(beanClass); if (BeanTransformer.skipForInitializer(thisPackage, beanClass)) { continue; } String dtoName = thisPackage.getName() + "." + context.classesNameTranslation.get(beanClass); String simpleDtoName = JavaGeneratorUtil.getSimpleName(dtoName); String methodName = getMethodName(useRelativeName, relativeNameExcludes, "init", null, dtoName); ObjectModelOperation operation = addOperation(output, methodName, "void", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, operation, Override.class); if (context.selectedClasses.contains(beanClass)) { boolean referential = BinderHelper.isReferentialFromPackageName(beanClass.getPackageName()); StringBuilder body = new StringBuilder(); boolean withReference = withReferenceFqns.contains(fqn); boolean withForm = withFormFqns.contains(fqn); if (withForm) { // add dto binder String binderMethodName = referential ? "registerDtoReferentialBinder" : "registerDtoDataBinder"; String binderName = BinderHelper.generateBinderName(binderPackageName, fqn, beanClass.getName() + "EntityDto"); if (!useRelativeName) { addImport(output, binderName); binderName = JavaGeneratorUtil.getSimpleName(binderName); } body.append("" +"\n" +" "+binderMethodName+"(new "+binderName+"());"); } if (withReference) { // add reference binder String binderMethodName = referential ? "registerReferenceReferentialBinder" : "registerReferenceDataBinder"; String binderName = BinderHelper.generateBinderName(binderPackageName, fqn, beanClass.getName() + "EntityReference"); if (!useRelativeName) { addImport(output, fqn + "Reference"); addImport(output, binderName); binderName = JavaGeneratorUtil.getSimpleName(binderName); } body.append("" +"\n" +" "+binderMethodName+"(new "+binderName+"());"); } setOperationBody(operation, body.toString()+"\n" +" "); } } } private void generateBinderClass(ObjectModelClass input, boolean useRelativeName, String dtoName, String className, String binderFullClassName, String superClass, Map properties) { String binderClassName = JavaGeneratorUtil.getSimpleName(binderFullClassName); ObjectModelClass output = createClass(binderClassName, binderFullClassName.substring(0, binderFullClassName.lastIndexOf("."))); String entityName = input.getName(); ObjectModelClass entityClass = context.selectedClassesByFqn.get(BinderHelper.cleanId(input.getQualifiedName())); String entityTypePackage = getEntityPackage(entityClass); setSuperClass(output, superClass); addImport(output, input.getPackageName() + "." + dtoName); addImport(output, input.getPackageName() + "." + className); addImport(output, entityTypePackage + "." + input.getName()); getLog().debug("will generate " + output.getQualifiedName()); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC); setOperationBody(constructor, ""+"\n" +" super("+dtoName+".class, "+className+".class, "+entityName+".class);\n" +" "); ObjectModelOperation operation = addOperation(output, "toReference", className, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, operation, Override.class); addParameter(operation, ReferentialLocale.class, "referentialLocale"); addParameter(operation, input.getName(), "entity"); int prefixLength = (" return new " + className + "(").length(); String prefix = StringUtils.leftPad("", prefixLength, " "); StringBuilder body = new StringBuilder(""+"\n" +" return new "+className+"(entity,"); Iterator> iterator = properties.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); ObjectModelAttribute attr = entry.getKey(); ObjectModelAttribute dtoAttr = entry.getValue(); String content = ""; if (dtoAttr != null) { String getterName; String type = JavaGeneratorUtil.getSimpleName(dtoAttr.getType()); String dtoAttrname = dtoAttr.getName(); boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(dtoAttr); if (booleanProperty) { getterName = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX; } else { getterName = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX; } getterName += JavaGeneratorUtil.capitalizeJavaBeanPropertyName(dtoAttrname); content = "entity." + getterName + "()"; if (context.selectedClassesFqn.contains(BinderHelper.cleanId(dtoAttr.getType()))) { entityClass = context.selectedClassesByFqn.get(BinderHelper.cleanId(dtoAttr.getType())); entityTypePackage = getEntityPackage(entityClass); String entityType = entityClass.getName(); // Dto if (!type.endsWith("Reference")) { // not a ref, get a ref type = BinderHelper.cleanId(type) + "Reference"; } String entityTypeFqn = useRelativeName ? entityTypePackage + "." + entityType : entityType; if (attr.getName().equals(dtoAttrname + "Id")) { if (!useRelativeName) { addImport(output, entityTypeFqn); } addImport(output, Optional.class); addImport(output, IdDto.class); content = String.format("Optional.ofNullable(%s).map(%s::getTopiaId).orElse(null)", content, entityTypeFqn); } else if (attr.getName().equals(dtoAttrname + "Label")) { if (!useRelativeName) { addImport(output, entityTypeFqn); } addImport(output, Optional.class); addImport(output, IdDto.class); String method = "getLabel(referentialLocale)"; if (type.equals("SpeciesReference")) { method = "getScientificLabel()"; } content = String.format("Optional.ofNullable(%s).map(e-> e.%s).orElse(null)", content, method); } else if (attr.getName().equals(dtoAttrname + "Code")) { if (!useRelativeName) { addImport(output, entityTypeFqn); } addImport(output, Optional.class); addImport(output, IdDto.class); content = String.format("Optional.ofNullable(%s).map(%s::getCode).orElse(null)", content, entityTypeFqn); } else { // Reference content = "toDataReference(referentialLocale, " + content + ")"; } } } else { if (attr.getName().equals("label")) { content = "entity.getLabel(referentialLocale)"; } else { content = "null"; } } content = prefix + content; String coma = iterator.hasNext() ? "," : ""; body.append(""+"\n" +""+content+""+coma+"" ); } body.append(""+");\n" +" "); setOperationBody(operation, body.toString()); } private void generateInitializer(String initializerPackageName, String generatedInitializerName, String initializerName) { ObjectModelClass output = createClass(initializerName, initializerPackageName); setSuperClass(output, generatedInitializerName); getLog().debug("will generate " + output.getQualifiedName()); } private boolean notFoundInClassPath(String input, String className) { String fqn = input + "." + className; boolean inClassPath = getResourcesHelper().isJavaFileInClassPath(fqn); return !inClassPath; } private String getAttributeType(String attrType) { if (!JavaGeneratorUtil.isPrimitiveType(attrType)) { boolean hasClass = model.hasClass(attrType); if (hasClass) { ObjectModelClass attributeClass = model.getClass(attrType); String attributeType = context.classesNameTranslation.get(attributeClass); if (attributeType != null) { attrType = attributeClass.getPackageName() + "." + attributeType; } } } return attrType; } private String getEntityPackage(ObjectModelClass entityClass) { return "fr.ird.observe.entities" + BinderHelper.getRelativeDtoPackage(entityClass.getPackageName()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy