fr.ird.observe.toolkit.templates.entity.ReferentialExtraScriptsGenerator Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates.entity;
/*-
* #%L
* Toolkit :: Templates
* %%
* Copyright (C) 2017 - 2024 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.Maps;
import com.google.common.collect.Multimap;
import fr.ird.observe.entities.referential.I18nReferentialEntity;
import fr.ird.observe.entities.referential.ReferentialEntity;
import fr.ird.observe.spi.context.ReferentialDtoEntityContext;
import fr.ird.observe.spi.referential.ReferentialExtraScripts;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.Template;
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.ObjectModelClassifier;
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.topia.service.sql.metadata.TopiaMetadataAssociation;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataComposition;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntity;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataLink;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModel;
import org.nuiton.topia.templates.TopiaExtensionTagValues;
import org.nuiton.topia.templates.TopiaHibernateTagValues;
import org.nuiton.topia.templates.TopiaTemplateHelper;
import org.nuiton.topia.templates.sql.TopiaMetadataModelBuilder;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Generate update script for a referential type.
*
* Created on 17/08/2022.
*
* @author Tony Chemit - [email protected]
* @since 9.0.7
*/
@Component(role = Template.class, hint = "fr.ird.observe.toolkit.templates.entity.ReferentialExtraScriptsGenerator")
public class ReferentialExtraScriptsGenerator extends ObjectModelTransformerToJava {
protected final TopiaExtensionTagValues topiaExtensionTagValues;
protected final TopiaHibernateTagValues topiaHibernateTagValues;
private TopiaMetadataModel metadataModel;
private final Map fqnToMetadata = new LinkedHashMap<>();
public ReferentialExtraScriptsGenerator() {
topiaHibernateTagValues = new TopiaHibernateTagValues();
topiaExtensionTagValues = new TopiaExtensionTagValues();
}
@Override
public void transformFromModel(ObjectModel model) {
setConstantPrefix("PROPERTY_");
TopiaTemplateHelper templateHelper = new TopiaTemplateHelper(model);
metadataModel = TopiaMetadataModelBuilder.build(isVerbose(), model, templateHelper);
List entityClasses = templateHelper.getEntityClasses(model, true);
for (ObjectModelClass entityClass : entityClasses) {
if (entityClass.isAbstract()) {
continue;
}
String fullyQualifiedName = entityClass.getQualifiedName();
if (!fullyQualifiedName.contains(".referential")) {
continue;
}
String literalName = templateHelper.getEntityEnumLiteralName(entityClass);
TopiaMetadataEntity metadataEntity = metadataModel.getEntity(literalName);
fqnToMetadata.put(fullyQualifiedName, metadataEntity);
}
super.transformFromModel(model);
}
@SuppressWarnings({"StringOperationCanBeSimplified"})
@Override
public void transformFromClass(ObjectModelClass input) {
TopiaMetadataEntity metadataEntity = fqnToMetadata.get(input.getQualifiedName());
if (metadataEntity == null) {
return;
}
Set compositions = metadataModel.getCompositions(metadataEntity);
Set associations = metadataModel.getAssociations(metadataEntity);
ObjectModelPackage aPackage = getPackage(input);
boolean i18n = false;
for (ObjectModelClass superclass : input.getSuperclasses()) {
if (I18nReferentialEntity.class.getName().equals(superclass.getQualifiedName())) {
i18n = true;
break;
}
}
String inputName = input.getName();
ObjectModelClass output = createClass(inputName + "ExtraScripts", input.getPackageName());
Class> superClass = ReferentialExtraScripts.class;
setSuperClass(output, String.format("%s<%s>", superClass.getName(), inputName));
addImport(output, List.class);
addImport(output, Set.class);
addImport(output, Multimap.class);
addImport(output, StringBuilder.class);
addImport(output, ReferentialDtoEntityContext.class);
List simplePropertiesNames = new LinkedList<>();
simplePropertiesNames.add(ReferentialEntity.PROPERTY_CODE);
simplePropertiesNames.add(ReferentialEntity.PROPERTY_URI);
simplePropertiesNames.add(ReferentialEntity.PROPERTY_HOME_ID);
simplePropertiesNames.add(ReferentialEntity.PROPERTY_NEED_COMMENT);
simplePropertiesNames.add(ReferentialEntity.PROPERTY_STATUS);
if (i18n) {
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL1);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL2);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL3);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL4);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL5);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL6);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL7);
simplePropertiesNames.add(I18nReferentialEntity.PROPERTY_LABEL8);
}
simplePropertiesNames.addAll(metadataEntity.getProperties().keySet());
String simplePropertyNames = constantProperties(simplePropertiesNames, inputName);
String compositionPropertyNames = constantProperties(compositions.stream().map(TopiaMetadataLink::getTargetPropertyName).collect(Collectors.toList()), inputName);
String associationPropertyNames = constantProperties(associations.stream().map(TopiaMetadataLink::getTargetPropertyName).collect(Collectors.toList()), inputName);
ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC);
setOperationBody(constructor, ""+"\n"
+" super("+inputName+".SPI,\n"
+" Set.of("+simplePropertyNames+"),\n"
+" Set.of("+compositionPropertyNames+"),\n"
+" Set.of("+associationPropertyNames+"));\n"
+" ");
ImmutableMap otherPropertiesByName = Maps.uniqueIndex(input.getAllOtherAttributes(), ObjectModelAttribute::getName);
addUpdateMethods(input, output, metadataEntity, compositions, associations, aPackage, inputName, simplePropertiesNames, otherPropertiesByName);
// for copy add lastUpdateDate property as well
simplePropertiesNames.add(0, ReferentialEntity.PROPERTY_LAST_UPDATE_DATE);
addCopyMethods(input, output, metadataEntity, compositions, associations, aPackage, inputName, simplePropertiesNames, otherPropertiesByName);
addOptionalRecursiveProperty(output, metadataEntity, inputName);
}
private void addUpdateMethods(ObjectModelClass input,
ObjectModelClass output, TopiaMetadataEntity metadataEntity,
Set compositions,
Set associations,
ObjectModelPackage aPackage,
String inputName,
List simplePropertiesNames,
ImmutableMap otherPropertiesByName) {
ObjectModelOperation computeUpdateParametersOperation = addOperation(output, "computeUpdateParameters", void.class, ObjectModelJavaModifier.PROTECTED);
addAnnotation(output, computeUpdateParametersOperation, Override.class);
addParameter(computeUpdateParametersOperation, inputName, "entity");
addParameter(computeUpdateParametersOperation, "Set", "propertiesToProcess");
addParameter(computeUpdateParametersOperation, "StringBuilder", "parameters");
addParameter(computeUpdateParametersOperation, "Multimap, String>", "referentialShell");
StringBuilder bodyContent = new StringBuilder();
for (String attrName : simplePropertiesNames) {
String columnName = metadataEntity.getDbColumnName(attrName);
ObjectModelAttribute attribute = input.getAttribute(attrName);
if (attribute == null) {
attribute = otherPropertiesByName.get(attrName);
}
String attrType = getPropertyType(Objects.requireNonNull(attribute), input, aPackage);
attrType = GeneratorUtil.removeAnyGenericDefinition(attrType);
ObjectModelEnumeration enumeration = model.getEnumeration(attrType);
attrType = GeneratorUtil.getSimpleName(attrType);
String methodName = "addUpdateOtherTypeParameter";
if (enumeration != null) {
methodName = "addUpdateEnumParameter";
} else {
switch (attrType) {
case "boolean":
methodName = "addUpdatePrimitiveBooleanParameter";
break;
case "int":
methodName = "addUpdatePrimitiveIntegerParameter";
break;
case "long":
methodName = "addUpdatePrimitiveLongParameter";
break;
case "float":
methodName = "addUpdatePrimitiveFloatParameter";
break;
case "double":
methodName = "addUpdatePrimitiveDoubleParameter";
break;
case "Boolean":
methodName = "addUpdateBooleanParameter";
break;
case "Integer":
methodName = "addUpdateIntegerParameter";
break;
case "Long":
methodName = "addUpdateLongParameter";
break;
case "Float":
methodName = "addUpdateFloatParameter";
break;
case "Double":
methodName = "addUpdateDoubleParameter";
break;
case "String":
methodName = "addUpdateStringParameter";
break;
case "Date":
String type = topiaHibernateTagValues.getHibernateAttributeType(attribute, input, aPackage, model);
if (type == null) {
type = "timestamp";
}
switch (type) {
case "date":
methodName = "addUpdateDateParameter";
break;
case "time":
methodName = "addUpdateTimeParameter";
break;
case "timestamp":
methodName = "addUpdateTimestampParameter";
break;
}
break;
}
}
boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(attribute);
String getterName = getJavaBeanMethodName(booleanProperty ? JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX : JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, attrName);
bodyContent.append(""+"\n"
+" "+methodName+"(propertiesToProcess, "+inputName+"."+getConstantName(attrName)+", \""+columnName+"\", entity."+getterName+"(), parameters);");
}
for (TopiaMetadataComposition composition : compositions) {
String columnName = composition.getTargetDbName();
String propertyName = composition.getTargetPropertyName();
String getterName = getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, propertyName);
TopiaMetadataEntity targetMetadataEntity = composition.getTarget();
bodyContent.append(""+"\n"
+" addUpdateReferentialComposition(propertiesToProcess, "+targetMetadataEntity.getFullyQualifiedName()+".SPI, "+inputName+"."+getConstantName(propertyName)+", \""+columnName+"\", entity."+getterName+"(), parameters, referentialShell);");
}
setOperationBody(computeUpdateParametersOperation, bodyContent + ""+"\n"
+" ");
if (!associations.isEmpty()) {
addImport(output, List.class);
ObjectModelOperation computeAssociationsOperation = addOperation(output, "computeUpdateAssociations", void.class, ObjectModelJavaModifier.PROTECTED);
addAnnotation(output, computeAssociationsOperation, Override.class);
addParameter(computeAssociationsOperation, inputName, "entity");
addParameter(computeAssociationsOperation, "Set", "propertiesToProcess");
addParameter(computeAssociationsOperation, "Multimap, String>", "referentialShell");
addParameter(computeAssociationsOperation, "List", "result");
bodyContent = new StringBuilder();
for (TopiaMetadataAssociation association : associations) {
String propertyName = association.getTargetPropertyName();
String getterName = getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, propertyName);
String tableName = association.getTableName();
String sourceDbName = association.getSourceDbName();
String targetDbName = association.getTargetDbName();
TopiaMetadataEntity targetMetadataEntity = association.getTarget();
bodyContent.append(""+"\n"
+" addUpdateReferentialAssociation(propertiesToProcess, "+targetMetadataEntity.getFullyQualifiedName()+".SPI, "+inputName+"."+getConstantName(propertyName)+", \""+tableName+"\", \""+sourceDbName+"\", \""+targetDbName+"\", entity.getTopiaId(), entity."+getterName+"(), referentialShell, result);");
}
setOperationBody(computeAssociationsOperation, bodyContent + ""+"\n"
+" ");
}
}
private void addCopyMethods(ObjectModelClass input,
ObjectModelClass output,
TopiaMetadataEntity metadataEntity,
Set compositions, Set associations, ObjectModelPackage aPackage,
String inputName,
List simplePropertiesNames,
ImmutableMap otherPropertiesByName) {
ObjectModelOperation computeInsertColumnAndParametersOperation = addOperation(output, "computeInsertColumnAndParameters", void.class, ObjectModelJavaModifier.PROTECTED);
addAnnotation(output, computeInsertColumnAndParametersOperation, Override.class);
addParameter(computeInsertColumnAndParametersOperation, inputName, "entity");
addParameter(computeInsertColumnAndParametersOperation, "List", "columnNames");
addParameter(computeInsertColumnAndParametersOperation, "List", "parameters");
addParameter(computeInsertColumnAndParametersOperation, "Multimap, String>", "referentialShell");
StringBuilder bodyContent = new StringBuilder(""+"\n"
+" addInsertStringParameter(\"topiaId\", entity.getId(), columnNames, parameters);\n"
+" addInsertLongParameter(\"topiaVersion\", entity.getTopiaVersion(), columnNames, parameters);\n"
+" addInsertTimestampParameter(\"topiaCreateDate\", entity.getTopiaCreateDate(), columnNames, parameters);");
for (String attrName : simplePropertiesNames) {
String columnName = metadataEntity.getDbColumnName(attrName);
ObjectModelAttribute attribute = input.getAttribute(attrName);
if (attribute == null) {
attribute = otherPropertiesByName.get(attrName);
}
String attrType = getPropertyType(Objects.requireNonNull(attribute), input, aPackage);
attrType = GeneratorUtil.removeAnyGenericDefinition(attrType);
ObjectModelEnumeration enumeration = model.getEnumeration(attrType);
attrType = GeneratorUtil.getSimpleName(attrType);
String methodName = "addInsertOtherTypeParameter";
if (enumeration != null) {
methodName = "addInsertEnumParameter";
} else {
switch (attrType) {
case "boolean":
methodName = "addInsertPrimitiveBooleanParameter";
break;
case "int":
methodName = "addInsertPrimitiveIntegerParameter";
break;
case "long":
methodName = "addInsertPrimitiveLongParameter";
break;
case "float":
methodName = "addInsertPrimitiveFloatParameter";
break;
case "double":
methodName = "addInsertPrimitiveDoubleParameter";
break;
case "Boolean":
methodName = "addInsertBooleanParameter";
break;
case "Integer":
methodName = "addInsertIntegerParameter";
break;
case "Long":
methodName = "addInsertLongParameter";
break;
case "Float":
methodName = "addInsertFloatParameter";
break;
case "Double":
methodName = "addInsertDoubleParameter";
break;
case "String":
methodName = "addInsertStringParameter";
break;
case "Date":
String type = topiaHibernateTagValues.getHibernateAttributeType(attribute, input, aPackage, model);
if (type == null) {
type = "timestamp";
}
switch (type) {
case "date":
methodName = "addInsertDateParameter";
break;
case "time":
methodName = "addInsertTimeParameter";
break;
case "timestamp":
methodName = "addInsertTimestampParameter";
break;
}
break;
}
}
boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(attribute);
String getterName = getJavaBeanMethodName(booleanProperty ? JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX : JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, attrName);
bodyContent.append(""+"\n"
+" "+methodName+"(\""+columnName+"\", entity."+getterName+"(), columnNames, parameters);");
}
for (TopiaMetadataComposition composition : compositions) {
String columnName = composition.getTargetDbName();
String getterName = getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, composition.getTargetPropertyName());
TopiaMetadataEntity targetMetadataEntity = composition.getTarget();
bodyContent.append(""+"\n"
+" addInsertReferentialComposition("+targetMetadataEntity.getFullyQualifiedName()+".SPI, \""+columnName+"\", entity."+getterName+"(), columnNames, parameters, referentialShell);");
}
setOperationBody(computeInsertColumnAndParametersOperation, bodyContent + ""+"\n"
+" ");
if (!associations.isEmpty()) {
ObjectModelOperation computeAssociationsOperation = addOperation(output, "computeInsertAssociations", void.class, ObjectModelJavaModifier.PROTECTED);
addAnnotation(output, computeAssociationsOperation, Override.class);
addParameter(computeAssociationsOperation, inputName, "entity");
addParameter(computeAssociationsOperation, "Multimap, String>", "referentialShell");
addParameter(computeAssociationsOperation, "List", "result");
bodyContent = new StringBuilder();
for (TopiaMetadataAssociation association : associations) {
String getterName = getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, association.getTargetPropertyName());
String tableName = association.getTableName();
String sourceDbName = association.getSourceDbName();
String targetDbName = association.getTargetDbName();
TopiaMetadataEntity targetMetadataEntity = association.getTarget();
bodyContent.append(""+"\n"
+" addInsertReferentialAssociation("+targetMetadataEntity.getFullyQualifiedName()+".SPI, \""+tableName+"\", \""+sourceDbName+"\", \""+targetDbName+"\", entity.getTopiaId(), entity."+getterName+"(), referentialShell, result);");
}
setOperationBody(computeAssociationsOperation, bodyContent + ""+"\n"
+" ");
}
}
private void addOptionalRecursiveProperty(ObjectModelClass output, TopiaMetadataEntity metadataEntity, String inputName) {
String optionalRecursiveProperty = metadataEntity.getOptionalRecursiveProperty().orElse(null);
if (optionalRecursiveProperty != null) {
addImport(output, Optional.class);
ObjectModelOperation getOptionalRecursivePropertyOperation = addOperation(output, "getOptionalRecursiveProperty", "Optional", ObjectModelJavaModifier.PUBLIC);
addAnnotation(output, getOptionalRecursivePropertyOperation, Override.class);
setOperationBody(getOptionalRecursivePropertyOperation, ""+"\n"
+" return Optional.of("+inputName+"."+getConstantName(optionalRecursiveProperty)+");\n"
+" ");
}
}
private String constantProperties(Collection propertyNames, String inputName) {
StringBuilder simplePropertyNamesBuilder = new StringBuilder();
for (String propertyName : propertyNames) {
simplePropertyNamesBuilder.append(""+", "+inputName+"."+getConstantName(propertyName)+"");
}
return simplePropertyNamesBuilder.length() == 0 ? "" : simplePropertyNamesBuilder.substring(2);
}
private String getPropertyType(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String propertyType = topiaHibernateTagValues.getAttributeType(attribute, aClass, aPackage, model);
if (propertyType == null) {
propertyType = attribute.getType();
}
return propertyType;
}
}