fr.ird.observe.toolkit.templates.entity.ToolkitEntityTransformer 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.auto.service.AutoService;
import com.google.common.collect.ImmutableMap;
import fr.ird.observe.dto.BusinessDto;
import fr.ird.observe.dto.DtoParentAware;
import fr.ird.observe.dto.data.ContainerDto;
import fr.ird.observe.dto.data.DataDto;
import fr.ird.observe.dto.data.DataGroupByType;
import fr.ird.observe.dto.data.EditableDto;
import fr.ird.observe.dto.data.OpenableDto;
import fr.ird.observe.dto.data.SimpleDto;
import fr.ird.observe.dto.reference.DtoReference;
import fr.ird.observe.dto.referential.ReferentialLocale;
import fr.ird.observe.entities.Entity;
import fr.ird.observe.entities.data.DataEntity;
import fr.ird.observe.entities.data.DataGroupByEntityAbstract;
import fr.ird.observe.entities.data.DataGroupByEntityDefinition;
import fr.ird.observe.entities.referential.I18nReferentialEntity;
import fr.ird.observe.entities.referential.ReferentialEntity;
import fr.ird.observe.spi.PersistenceBusinessProject;
import fr.ird.observe.spi.ProjectPackagesDefinition;
import fr.ird.observe.spi.context.ContainerDtoEntityContext;
import fr.ird.observe.spi.context.DataDtoEntityContext;
import fr.ird.observe.spi.context.DtoEntityContext;
import fr.ird.observe.spi.context.EditableDtoEntityContext;
import fr.ird.observe.spi.context.OpenableDtoEntityContext;
import fr.ird.observe.spi.context.ReferentialDtoEntityContext;
import fr.ird.observe.spi.context.RootOpenableDtoEntityContext;
import fr.ird.observe.spi.context.SimpleDtoEntityContext;
import fr.ird.observe.spi.mapping.DtoToEntityContextMapping;
import fr.ird.observe.spi.mapping.EntityToDtoClassMapping;
import fr.ird.observe.spi.module.BusinessModule;
import fr.ird.observe.spi.navigation.model.MetaModelSupport;
import fr.ird.observe.spi.navigation.model.tree.TreeNodeModel;
import fr.ird.observe.spi.navigation.model.tree.TreeProjectModel;
import fr.ird.observe.spi.navigation.model.tree.TreeProjectModelBuilder;
import fr.ird.observe.spi.navigation.parent.ParentLink;
import fr.ird.observe.spi.navigation.parent.ParentProjectModel;
import fr.ird.observe.spi.relation.MultipleDtoEntityRelation;
import fr.ird.observe.spi.relation.SingleDtoEntityRelation;
import fr.ird.observe.spi.relation.WithDtoEntityRelation;
import fr.ird.observe.spi.result.AddEntityToUpdateStep;
import fr.ird.observe.toolkit.templates.TemplateContract;
import fr.ird.observe.toolkit.templates.ToolkitTagValues;
import fr.ird.observe.toolkit.templates.dto.stats.StatisticDefinitionModel;
import fr.ird.observe.toolkit.templates.dto.stats.StatisticsHelper;
import fr.ird.observe.toolkit.templates.validation.ValidationTagValues;
import io.ultreia.java4all.bean.definition.JavaBeanDefinition;
import io.ultreia.java4all.bean.definition.JavaBeanDefinitionStore;
import io.ultreia.java4all.bean.spi.GenerateJavaBeanDefinition;
import io.ultreia.java4all.classmapping.ImmutableClassMapping;
import io.ultreia.java4all.lang.Strings;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.extension.ImportsManager;
import org.nuiton.eugene.java.extension.ObjectModelAnnotation;
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.ObjectModelElement;
import org.nuiton.eugene.models.object.ObjectModelEnumeration;
import org.nuiton.eugene.models.object.ObjectModelInterface;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.eugene.models.object.ObjectModelParameter;
import org.nuiton.eugene.models.object.xml.ObjectModelAttributeImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelInterfaceImpl;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaPersistenceContext;
import org.nuiton.topia.persistence.filter.EntityFilterConsumer;
import org.nuiton.topia.persistence.filter.EntityFilterProperty;
import org.nuiton.topia.persistence.filter.property.BooleanFilterProperty;
import org.nuiton.topia.persistence.filter.property.DateFilterProperty;
import org.nuiton.topia.persistence.filter.property.DoubleFilterProperty;
import org.nuiton.topia.persistence.filter.property.EnumFilterProperty;
import org.nuiton.topia.persistence.filter.property.FloatFilterProperty;
import org.nuiton.topia.persistence.filter.property.IdFilterProperty;
import org.nuiton.topia.persistence.filter.property.IntegerFilterProperty;
import org.nuiton.topia.persistence.filter.property.LongFilterProperty;
import org.nuiton.topia.persistence.filter.property.StringFilterProperty;
import org.nuiton.topia.persistence.filter.property.TimeFilterProperty;
import org.nuiton.topia.persistence.filter.property.TimestampFilterProperty;
import org.nuiton.topia.persistence.internal.AbstractTopiaEntity;
import org.nuiton.topia.service.sql.TopiaEntitySqlModelResource;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntity;
import org.nuiton.topia.service.sql.model.TopiaEntitySqlDescriptor;
import org.nuiton.topia.service.sql.script.TopiaEntitySqlScript;
import org.nuiton.topia.templates.EntityTransformer;
import java.beans.Introspector;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* A template to generate all the {@link TopiaEntity} api for all classifier
* with a {@code entity} stereotype.
*
* For example, given a {@code House} entity, it will generates :
*
* - {@code House} : contract of entity
* - {@code AbstractHouse} : default abstract implementation of entity
* - {@code HouseImpl} : default impl of abstract entity
*
*
* Note: The impl will ony be generated in these cases :
*
* - There is no abstract method
* - There is no already defined such class in class-path
*
*
* @author Tony Chemit - [email protected]
* @since 2.3.4
*/
@SuppressWarnings({"StringOperationCanBeSimplified", "CommentedOutCode", "unused"})
public class ToolkitEntityTransformer extends EntityTransformer implements TemplateContract {
private static final Logger log = LogManager.getLogger(ToolkitEntityTransformer.class);
private final Set spiMethodNames;
private final Map dtoToEntityContextMapping = new TreeMap<>();
private final Map entityToDtoClassMapping = new TreeMap<>();
private final List groupByDtoDefinitionMapping = new LinkedList<>();
private final ToolkitTagValues toolkitTagValues;
private final ValidationTagValues validationTagValues;
protected boolean doReference;
private Class extends DtoReference> referenceContractType;
private Class extends BusinessDto> dtoContractType;
private Class extends BusinessDto> dtoType;
private Class extends DtoReference> referenceType;
private String parentWithGeneric;
private String[] relativeNameExcludes;
private List entityClasses;
private List entityClassesFully;
private ProjectPackagesDefinition def;
private List entityClassesEntryPoints;
private ParentProjectModel parentProjectModel;
private TreeProjectModel navigationProjectModel;
private List statisticDefinitions;
public ToolkitEntityTransformer() {
this.toolkitTagValues = new ToolkitTagValues();
spiMethodNames = new LinkedHashSet<>();
spiMethodNames.add("fromDto");
spiMethodNames.add("getDao");
spiMethodNames.add("entityToForm");
spiMethodNames.add("loadEntityToReferenceDto");
spiMethodNames.add("loadEntityToDto");
spiMethodNames.add("loadEntities");
spiMethodNames.add("loadOrCreateEntity");
spiMethodNames.add("loadEntity");
spiMethodNames.add("loadEntitiesToDto");
spiMethodNames.add("loadReference");
spiMethodNames.add("loadOrCreateEntityFromDto");
spiMethodNames.add("loadNullableEntity");
spiMethodNames.add("newEntity");
spiMethodNames.add("newDto");
spiMethodNames.add("toReferenceSet");
spiMethodNames.add("toDto");
spiMethodNames.add("toReference");
spiMethodNames.add("toReferenceType");
spiMethodNames.add("toEntity");
spiMethodNames.add("toDtoSet");
spiMethodNames.add("toDtoList");
spiMethodNames.add("toLabelList");
spiMethodNames.add("toReferenceLabelList");
spiMethodNames.add("toDtoType");
spiMethodNames.add("usageModel");
validationTagValues = new ValidationTagValues();
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
protected void setDoDto(ObjectModelClass input) {
super.setDoDto(input);
boolean isAbstract = input.isAbstract() && !input.isStatic();
doReference = doDto && !isAbstract && entityToDtoMapping.acceptReference(input);
if (doDto) {
dtoContractType = ((ToolkitEntityToDtoMapping) entityToDtoMapping).getDtoContract2();
referenceContractType = ((ToolkitEntityToDtoMapping) entityToDtoMapping).getReferenceType(dtoContractType);
dtoType = (Class extends BusinessDto>) entityToDtoMapping.getDtoType();
Collection extends ObjectModelClassifier> classifiersToTest = new LinkedList<>(input.getInterfaces());
classifiersToTest.addAll((Collection) input.getSuperclasses());
for (ObjectModelClassifier parent : classifiersToTest) {
ObjectModelClass parent1 = model.getClass(parent.getQualifiedName());
if (parent1 != null && templateHelper.isEntity(parent1)) {
parentWithGeneric = parent.getQualifiedName();
break;
}
}
}
if (doReference) {
referenceType = ((ToolkitEntityToDtoMapping) entityToDtoMapping).getReferenceType(dtoType);
}
}
@Override
public void transformFromModel(ObjectModel model) {
def = ProjectPackagesDefinition.of(getClassLoader());
EugeneCoreTagValues coreTagValues = new EugeneCoreTagValues();
Set relativeNameExcludes = coreTagValues.getRelativeNameExcludes(model);
this.relativeNameExcludes = relativeNameExcludes == null ? new String[0] : relativeNameExcludes.toArray(new String[0]);
MetaModelSupport metaModelSupport = new MetaModelSupport(model.getName());
navigationProjectModel = metaModelSupport.getTreeNavigationProjectModel();
parentProjectModel = metaModelSupport.getParentProjectModel();
List entityClasses = templateHelper.getEntityClasses(model, false);
this.entityClasses = entityClasses.stream().map(ObjectModelClass::getName).collect(Collectors.toList());
entityClassesFully = entityClasses.stream().map(ObjectModelClass::getQualifiedName).collect(Collectors.toList());
this.entityClassesEntryPoints = entityClasses.stream().filter(topiaExtensionTagValues::isEntryPoint).map(ObjectModelClass::getQualifiedName).collect(Collectors.toCollection(LinkedList::new));
super.transformFromModel(model);
}
@Override
protected void debugOutputModel() {
super.debugOutputModel();
generateClassMapping(true, DtoToEntityContextMapping.class, "Class extends " + BusinessDto.class.getName() + ">", DtoEntityContext.class.getName() + ", ?, ?, ?>", ImmutableMap.class, "build", dtoToEntityContextMapping);
generateClassMapping(true, EntityToDtoClassMapping.class, Entity.class.getName(), BusinessDto.class.getName(), ImmutableClassMapping.class, "getMappingBuilder", entityToDtoClassMapping);
String businessProjectClassName = generateBusinessProject(model.getName());
if (isVerbose()) {
getLog().info("Generated: " + businessProjectClassName);
}
}
@Override
protected boolean isGenerateAbstract(ObjectModelClass input) {
if (Entity.class.getName().equals(input.getQualifiedName())) {
return false;
}
return super.isGenerateAbstract(input);
}
@Override
protected boolean isGenerateImpl(ObjectModelClass input) {
if (ReferentialEntity.class.getName().equals(input.getQualifiedName())) {
return true;
}
if (I18nReferentialEntity.class.getName().equals(input.getQualifiedName())) {
return true;
}
if (DataEntity.class.getName().equals(input.getQualifiedName())) {
return true;
}
return super.isGenerateImpl(input);
}
@SuppressWarnings("unused")
private String generateBusinessProject(String name) {
String className = String.format("%s%s", name, PersistenceBusinessProject.class.getSimpleName());
ObjectModelClass aClass = createClass(className, PersistenceBusinessProject.class.getPackage().getName());
ObjectModelAnnotation annotation = addAnnotation(aClass, aClass, AutoService.class);
ImportsManager importManager = getImportManager(aClass);
addAnnotationClassParameter(importManager, aClass, annotation, "value", PersistenceBusinessProject.class);
setSuperClass(aClass, PersistenceBusinessProject.class);
addImport(aClass, List.class);
addImport(aClass, BusinessModule.class);
ObjectModelOperation getOperation = addOperation(aClass, "get", className, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
setOperationBody(getOperation, ""+"\n"
+" return ("+className+") PersistenceBusinessProject.get();\n"
+" ");
ObjectModelOperation constructor = addConstructor(aClass, ObjectModelJavaModifier.PUBLIC);
String entityToDtoMapping = EntityToDtoClassMapping.class.getPackage().getName() + "." + name + EntityToDtoClassMapping.class.getSimpleName();
String dtoToEntityContextMapping = DtoToEntityContextMapping.class.getPackage().getName() + "." + name + DtoToEntityContextMapping.class.getSimpleName();
List tmp = new LinkedList<>();
for (String groupBy : groupByDtoDefinitionMapping) {
tmp.add(",\n " + groupBy);
}
String groupByDtoDefinition = String.join("", tmp).substring(1);
setOperationBody(constructor, ""+"\n"
+" super("+entityToDtoMapping+".get(), "+dtoToEntityContextMapping+".get(),"+groupByDtoDefinition+");\n"
+" ");
return aClass.getQualifiedName();
}
@Override
protected void createEntityInterface(ObjectModelPackage aPackage, ObjectModelClass input) {
statisticDefinitions = null;
if (doDto && dtoType != null) {
String[] statisticsTagValue = ((ToolkitEntityToDtoMapping) entityToDtoMapping).getStatisticsTagValue(dtoType);
statisticDefinitions = statisticsTagValue == null ? null : StatisticsHelper.toModel(model, input, def, Objects.requireNonNull(statisticsTagValue));
}
boolean isAbstract = input.isAbstract() && !input.isStatic();
if (isAbstract && doDto) {
String name = input.getName();
if (generateInterface) {
outputInterface = createInterface(name, input.getPackageName());
} else {
outputInterface = new ObjectModelInterfaceImpl();
((ObjectModelInterfaceImpl) outputInterface).setName(name);
}
} else {
if (generateInterface) {
outputInterface = createInterface(input.getName(), input.getPackageName());
} else {
outputInterface = new ObjectModelInterfaceImpl();
((ObjectModelInterfaceImpl) outputInterface).setName(input.getName());
}
}
addImport(outputInterface, outputInterface.getQualifiedName());
if (!generateInterface) {
return;
}
// Documentation
if (GeneratorUtil.hasDocumentation(input)) {
setDocumentation(outputInterface, input.getDocumentation());
}
addAnnotation(outputInterface, outputInterface, GenerateJavaBeanDefinition.class);
boolean oneParentContainsEntity = false;
List interfaceAlreadyDone = new LinkedList<>();
for (ObjectModelClassifier parent : input.getInterfaces()) {
if (doDto) {
Set parents = collectAllInterfaces(parent);
oneParentContainsEntity = parents.contains(Entity.class.getName());
if (parent.getQualifiedName().equals(parentWithGeneric)) {
addImport(outputInterface, parentWithGeneric);
addInterface(interfaceAlreadyDone, outputInterface, parentWithGeneric);
continue;
}
if (oneParentContainsEntity) {
addImport(outputInterface, parent.getQualifiedName());
addInterface(interfaceAlreadyDone, outputInterface, parent.getQualifiedName());
continue;
}
}
addInterface(interfaceAlreadyDone, outputInterface, parent);
}
for (ObjectModelClassifier parent : input.getSuperclasses()) {
if (templateHelper.isEntity(parent)) {
if (doDto) {
if (isAbstract) {
addInterface(interfaceAlreadyDone, outputInterface, parent.getQualifiedName());
} else {
if (oneParentContainsEntity) {
continue;
}
addInterface(interfaceAlreadyDone, outputInterface, parent.getQualifiedName());
}
} else {
addInterface(interfaceAlreadyDone, outputInterface, parent);
}
}
}
if (generateInterface && doDto && !isAbstract) {
String persistenceContext = getDefaultPackageName() + "." + templateHelper.getPersistenceContextConcreteName(model);
addImport(outputInterface, persistenceContext);
boolean referential = TemplateContract.isReferentialFromPackageName(aPackage.getName());
addWithNoCodeInterface(referential, input, outputInterface);
}
if (!isAbstract) {
generateJavaBeanMethods();
}
addContractTypeMethod(input, outputInterface);
}
@SuppressWarnings("UnusedAssignment")
@Override
protected void closeAcceptInternalOperation() {
super.closeAcceptInternalOperation();
boolean isAbstract = input.isAbstract() && !input.isStatic();
if (generateInterface && doDto && !isAbstract) {
String daoMethodName = Strings.getRelativeCamelCaseName(getDefaultPackageName(), def.getRelativeEntityPackage(input.getQualifiedName() + "Dao"), relativeNameExcludes);
String entityName = input.getName();
String entityPackageName = input.getPackageName();
String daoName = entityName + "TopiaDao";
boolean referential = TemplateContract.isReferentialFromPackageName(entityPackageName);
boolean entryPoint = topiaExtensionTagValues.isEntryPoint(input);
String persistenceContext = getDefaultPackageName() + "." + templateHelper.getPersistenceContextConcreteName(model);
for (Class> dtoDtoType : entityToDtoMapping.getDtoTypes(input)) {
boolean mainSpi = dtoDtoType.getSimpleName().equals(entityName + "Dto");
boolean dtoEntryPoint = mainSpi && entryPoint;
boolean container = false;
String dtoTypeName = dtoDtoType.getSimpleName();
String spiClassName = dtoTypeName.replace("Dto", "Spi");
String generatedSpiClassName = "Generated" + spiClassName;
ObjectModelClass generatedSpi = createAbstractClass(generatedSpiClassName, entityPackageName);
addImport(generatedSpi, dtoDtoType);
addImport(generatedSpi, ReferentialLocale.class);
ToolkitEntityToDtoMapping entityToDtoMapping = (ToolkitEntityToDtoMapping) this.entityToDtoMapping;
@SuppressWarnings("unchecked") Class extends DtoReference> referenceType = entityToDtoMapping.getReferenceType((Class extends BusinessDto>) dtoDtoType);
boolean noReference = referenceType == null;
String referencesTagValue = null;
if (referenceType == null) {
referenceType = entityToDtoMapping.getReferenceType(dtoType);
}
addImport(generatedSpi, referenceType);
String resourceClassName = model.getName() + TopiaEntitySqlModelResource.class.getSimpleName();
{
addImport(generatedSpi, getDefaultPackageName() + "." + resourceClassName);
ObjectModelOperation operation = addOperation(generatedSpi, "loadEntitySqlDescriptor", TopiaEntitySqlDescriptor.class, ObjectModelJavaModifier.PROTECTED, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, operation, Override.class);
setOperationBody(operation, ""+"\n"
+" return "+resourceClassName+".get().getModel().getDescriptor(toEntityType());\n"
+" ");
operation = addOperation(generatedSpi, "loadSqlScript", TopiaEntitySqlScript.class, ObjectModelJavaModifier.PROTECTED, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, operation, Override.class);
setOperationBody(operation, ""+"\n"
+" return "+resourceClassName+".get().getScriptModel().getScript(toEntityType().getName());\n"
+" ");
}
if (referential) {
String updateClassName = entityName + "ExtraScripts";
ObjectModelOperation operation = addOperation(generatedSpi, "loadExtraScripts", updateClassName, ObjectModelJavaModifier.PROTECTED, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, operation, Override.class);
setOperationBody(operation, ""+"\n"
+" return new "+updateClassName+"();\n"
+" ");
generateReferentialSpi(
dtoTypeName,
generatedSpi,
referenceType,
entityName,
daoName
);
} else if (dtoEntryPoint) {
referencesTagValue = toolkitTagValues.getReferencesTagValue(input);
generateEntryPointSpi(
dtoTypeName,
generatedSpi,
referenceType,
entityName,
daoName
);
} else {
// any of data must have at least one default parent
TopiaMetadataEntity entity = metadataModel.getEntity(templateHelper.getEntityEnumLiteralName(input));
Pair pair = getParent(entityToDtoMapping, input, entity, dtoDtoType, entryPoint);
String parentType = pair == null ? null : pair.getValue();
@SuppressWarnings("unused") String parentPropertyName = pair == null ? null : pair.getKey();
String parentDtoTypeName = null;
String parentTypeName = null;
@SuppressWarnings("unused") boolean multiple = false;
if (parentType != null) {
if (!entityClassesFully.contains(parentType)) {
parentType = input.getQualifiedName();
}
parentDtoTypeName = importAndSimplify(generatedSpi, parentType.replace(".entities.", ".dto.") + "Dto");
parentTypeName = importAndSimplify(generatedSpi, parentType);
ObjectModelClass parentTypeClass = model.getClass(parentType);
TopiaMetadataEntity parentEntity = metadataModel.getEntity(templateHelper.getEntityEnumLiteralName(parentTypeClass));
//noinspection
multiple = parentEntity.getOneToManyAssociations().containsKey(parentPropertyName);
}
Class> superClass = guessSpiSuperClass(dtoDtoType);
container = ContainerDtoEntityContext.class.equals(superClass);
generateSpi(
dtoTypeName,
generatedSpi,
referenceType,
entityName,
daoName,
parentType,
superClass);
boolean editable = EditableDtoEntityContext.class.isAssignableFrom(superClass);
if (!entryPoint && parentType != null) {
String type;
if (multiple) {
type = importAndSimplify(generatedSpi, MultipleDtoEntityRelation.class.getName());
} else {
type = importAndSimplify(generatedSpi, SingleDtoEntityRelation.class.getName());
}
String relationPrototype;
String relationType;
String relationRef = null;
if (mainSpi || editable) {
relationRef = "RELATION";
relationPrototype = String.format("<%s, %s, %s, %s>", parentDtoTypeName, dtoTypeName, parentTypeName, entityName);
relationType = String.format("%s%s", type, relationPrototype);
@SuppressWarnings("unused") String constantName = getConstantName(parentPropertyName);
addConstant(generatedSpi,
"RELATION",
relationType,
""+" "+type+".create(\n"
+" "+parentDtoTypeName+".class,\n"
+" "+dtoTypeName+".class,\n"
+" "+parentTypeName+".class,\n"
+" "+entityName+".class,\n"
+" "+parentTypeName+"."+constantName+")",
ObjectModelJavaModifier.PUBLIC);
} else {
relationRef = entityName + ".SPI.relation()";
relationPrototype = String.format("<%s, %s, %s, %s>", parentDtoTypeName, importAndSimplify(generatedSpi, dtoType.getName()), parentTypeName, entityName);
relationType = String.format("%s%s", type, relationPrototype);
}
addInterface(generatedSpi, String.format("%s%s", WithDtoEntityRelation.class.getName(), relationPrototype));
{
ObjectModelOperation relationOperation = addOperation(generatedSpi, "relation", relationType, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, relationOperation, Override.class);
setOperationBody(relationOperation, ""+"\n"
+" return "+relationRef+";\n"
+" ");
}
if (editable) {
{
ObjectModelOperation parentSpiOperation = addOperation(generatedSpi, "parentSpi", parentType + "Spi", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, parentSpiOperation, Override.class);
setOperationBody(parentSpiOperation, ""+"\n"
+" return "+parentTypeName+".SPI;\n"
+" ");
}
{
ObjectModelOperation setNotPersistedEntityOperation = addOperation(generatedSpi, "setNotPersistedEntity", "void", ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, setNotPersistedEntityOperation, Override.class);
addParameter(setNotPersistedEntityOperation, parentTypeName, "parent");
addParameter(setNotPersistedEntityOperation, entityName, "entity");
@SuppressWarnings("unused") String methodName = (multiple ? "add" : "set") + Strings.capitalize(parentPropertyName);
setOperationBody(setNotPersistedEntityOperation, ""+"\n"
+" parent."+methodName+"(entity);\n"
+" ");
}
}
if (OpenableDtoEntityContext.class.isAssignableFrom(superClass)) {
{
ObjectModelOperation parentSpiOperation = addOperation(generatedSpi, "parentSpi", parentType + "Spi", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, parentSpiOperation, Override.class);
setOperationBody(parentSpiOperation, ""+"\n"
+" return "+parentTypeName+".SPI;\n"
+" ");
}
{
ObjectModelOperation getChildrenFromParentOperation = addOperation(generatedSpi, "getChildrenFromParent", Collection.class.getName() + "<" + entityName + ">", ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, getChildrenFromParentOperation, Override.class);
addParameter(getChildrenFromParentOperation, parentTypeName, "parent");
@SuppressWarnings("unused") String methodName = getJavaBeanMethodName("get", parentPropertyName);
setOperationBody(getChildrenFromParentOperation, ""+"\n"
+" return parent."+methodName+"();\n"
+" ");
}
{
ObjectModelOperation addChildrenToParentOperation = addOperation(generatedSpi, "addChildrenToParent", void.class, ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, addChildrenToParentOperation, Override.class);
addParameter(addChildrenToParentOperation, parentTypeName, "parent");
addParameter(addChildrenToParentOperation, entityName, "entity");
@SuppressWarnings("unused") String methodName = getJavaBeanMethodName("add", parentPropertyName);
setOperationBody(addChildrenToParentOperation, ""+"\n"
+" parent."+methodName+"(entity);\n"
+" ");
}
}
}
}
String fqn;
if (mainSpi) {
// generate main spi
fqn = generateMainSpi(dtoDtoType, entityPackageName, entityName, spiClassName);
// generate delegate methods
generateSpiDelegateMethods(referential, daoName);
// add filter methods on generated spi
addFilterMethods(input, generatedSpi, referential, entryPoint);
} else {
// generate not main spi
fqn = generateSubSpi(dtoDtoType, entityPackageName, entityName, spiClassName);
{
ObjectModelOperation newFilterConsumer = addOperation(generatedSpi, "newFilterConsumer", "EntityFilterConsumer<" + entityName + ">",
ObjectModelJavaModifier.PUBLIC,
ObjectModelJavaModifier.FINAL);
addParameter(newFilterConsumer, ReferentialLocale.class, "referentialLocale");
addAnnotation(generatedSpi, newFilterConsumer, Override.class);
addImport(generatedSpi, EntityFilterConsumer.class);
String mainSpiClassName = entityName + ".SPI";
setOperationBody(newFilterConsumer, ""+"\n"
+" return "+mainSpiClassName+".newFilterConsumer(referentialLocale);\n"
+" ");
}
}
dtoToEntityContextMapping.put(dtoDtoType.getName(), fqn);
generateSpiCommonMethods(input,
persistenceContext,
entityName,
daoName,
daoMethodName,
dtoDtoType,
dtoTypeName,
noReference,
referenceType,
generatedSpi,
referencesTagValue,
mainSpi,
container);
generateConcreteSpi(entityPackageName, spiClassName, generatedSpi);
List operations = generatedSpi.getOperations().stream().sorted(Comparator.comparing(ObjectModelElement::getName)).collect(Collectors.toList());
generatedSpi.getOperations().clear();
generatedSpi.getOperations().addAll(operations);
}
TemplateContract.addToLabel(this, outputAbstract, dtoType.getName());
}
}
protected void generateSpi(String dtoTypeName,
ObjectModelClass generatedSpi,
Class extends DtoReference> referenceType,
String entityName,
String daoName,
String parentType,
Class> superClass) {
String referenceTypeName = Objects.requireNonNull(referenceType).getSimpleName();
String spiClassPrototype;
if (EditableDtoEntityContext.class.isAssignableFrom(superClass) || OpenableDtoEntityContext.class.isAssignableFrom(superClass)) {
spiClassPrototype = String.format("<%s, %s, %s, %s, %s>", parentType, dtoTypeName, referenceTypeName, entityName, daoName);
} else {
spiClassPrototype = String.format("<%s, %s, %s, %s>", dtoTypeName, referenceTypeName, entityName, daoName);
}
String generatedSpiSuperClass = String.format("%s%s", superClass.getName(), spiClassPrototype);
setSuperClass(generatedSpi, generatedSpiSuperClass);
}
protected void generateEntryPointSpi(String dtoTypeName,
ObjectModelClass generatedSpi,
Class extends DtoReference> referenceType,
String entityName,
String daoName) {
String referenceTypeName = Objects.requireNonNull(referenceType).getSimpleName();
String spiClassPrototype = String.format("<%s, %s, %s, %s, %s>", dtoTypeName, referenceTypeName, entityName, daoName, entityName + "GroupByReferentialHelper");
String generatedSpiSuperClass = String.format("%s%s", RootOpenableDtoEntityContext.class.getName(), spiClassPrototype);
setSuperClass(generatedSpi, generatedSpiSuperClass);
}
protected void generateReferentialSpi(String dtoTypeName,
ObjectModelClass generatedSpi,
Class extends DtoReference> referenceType,
String entityName,
String daoName) {
String referenceTypeName = Objects.requireNonNull(referenceType).getSimpleName();
String spiClassPrototype = String.format("<%s, %s, %s, %s>", dtoTypeName, referenceTypeName, entityName, daoName);
String generatedSpiSuperClass = String.format("%s%s", ReferentialDtoEntityContext.class.getName(), spiClassPrototype);
setSuperClass(generatedSpi, generatedSpiSuperClass);
}
private void generateSpiCommonMethods(ObjectModelClass input,
@SuppressWarnings("unused") String persistenceContext,
String entityName,
String daoName,
@SuppressWarnings("unused") String daoMethodName,
Class> dtoDtoType,
String dtoTypeName,
boolean noReference,
Class> referenceType,
ObjectModelClass generatedSpi,
String referencesTagValue,
boolean mainSpi,
boolean container) {
TopiaMetadataEntity table = metadataModel.getEntity(templateHelper.getEntityEnumLiteralName(input));
{
ObjectModelOperation toEntityTypeOperation = addOperation(generatedSpi, "toEntityType", "Class<" + entityName + ">", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, toEntityTypeOperation, Override.class);
setOperationBody(toEntityTypeOperation, ""+"\n"
+" return "+entityName+".class;\n"
+" ");
}
{
ObjectModelOperation newEntityOperation = addOperation(generatedSpi, "newEntity", entityName, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, newEntityOperation, Override.class);
setOperationBody(newEntityOperation, ""+"\n"
+" return new "+entityName+"Impl();\n"
+" ");
}
{
ObjectModelOperation getDaoOperation = addOperation(generatedSpi, "getDao", daoName, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, getDaoOperation, Override.class);
addParameter(getDaoOperation, TopiaPersistenceContext.class, "persistenceContext");
setOperationBody(getDaoOperation, ""+"\n"
+" return (("+persistenceContext+") persistenceContext).get"+daoMethodName+"();\n"
+" ");
}
{
ObjectModelOperation toDtoTypeOperation = addOperation(generatedSpi, "toDtoType", "Class<" + dtoTypeName + ">", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, toDtoTypeOperation, Override.class);
setOperationBody(toDtoTypeOperation, ""+"\n"
+" return "+dtoTypeName+".class;\n"
+" ");
}
ObjectModelOperation spiToDtoOperation = addOperation(generatedSpi, "toDto", "void", ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, spiToDtoOperation, Override.class);
addParameter(spiToDtoOperation, ReferentialLocale.class, "referentialLocale");
addParameter(spiToDtoOperation, entityName, "entity");
addParameter(spiToDtoOperation, dtoTypeName, "dto");
setOperationBody(spiToDtoOperation, ""+"\n"
+" " + generateToDtoOperation(dtoDtoType).trim() + ""+"\n"
+" ");
ObjectModelOperation spiFromDtoOperation = addOperation(generatedSpi, "fromDto", "void", ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, spiFromDtoOperation, Override.class);
addParameter(spiFromDtoOperation, ReferentialLocale.class, "referentialLocale");
addParameter(spiFromDtoOperation, entityName, "entity");
addParameter(spiFromDtoOperation, dtoTypeName, "dto");
setOperationBody(spiFromDtoOperation, ""+"\n"
+" " + generateFromDtoOperation(dtoDtoType).trim() + ""+"\n"
+" ");
if (container) {
ObjectModelOperation saveCallbackOperation = addOperation(generatedSpi, "saveCallback", "void", ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, saveCallbackOperation, Override.class);
addParameter(saveCallbackOperation, AddEntityToUpdateStep.class, "saveHelper");
addParameter(saveCallbackOperation, entityName, "entity");
ObjectModelAttribute attribute;
if (mainSpi) {
// special cas, input is container also, we need to find out the unique association from table
attribute = input.getAttributes().stream().filter(e -> ((ToolkitEntityToDtoMapping) entityToDtoMapping).containerChildDataTypes(e.getType())).findFirst().orElse(null);
} else {
String childEntityName = dtoDtoType.getPackageName().replace("dto.", "entities.") + "." + dtoTypeName.substring(entityName.length(), dtoTypeName.length() - 3);
attribute = input.getAttributes().stream().filter(e -> e.getType().equals(childEntityName)).findFirst().orElse(null);
}
Objects.requireNonNull(attribute, "Can't find attribute for type: " + dtoDtoType.getName());
String spi = importAndSimplify(generatedSpi, attribute.getType()) + ".SPI";
String methodName = getJavaBeanMethodName("get", attribute.getName());
setOperationBody(saveCallbackOperation, ""+"\n"
+" saveHelper.updateCollection("+spi+", entity."+methodName+"());\n"
+" ");
}
if (!noReference) {
String referenceTypeSimpleName = referenceType.getSimpleName();
{
ObjectModelOperation spiToReferenceOperation = addOperation(generatedSpi, "toReference", referenceTypeSimpleName, ObjectModelJavaModifier.PUBLIC);
addAnnotation(generatedSpi, spiToReferenceOperation, Override.class);
addParameter(spiToReferenceOperation, ReferentialLocale.class, "referentialLocale");
addParameter(spiToReferenceOperation, dtoTypeName, "dto");
setOperationBody(spiToReferenceOperation, ""+"\n"
+" return "+referenceTypeSimpleName+".of(referentialLocale, dto);\n"
+" ");
}
{
ObjectModelOperation toReferenceTypeOperation = addOperation(generatedSpi, "toReferenceType", "Class<" + referenceTypeSimpleName + ">", ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, toReferenceTypeOperation, Override.class);
setOperationBody(toReferenceTypeOperation, ""+"\n"
+" return "+referenceTypeSimpleName+".class;\n"
+" ");
}
}
if (referencesTagValue != null) {
String query = ToolkitEntityHibernateMappingTransformer.getReferenceQuery(table, referencesTagValue);
addConstant(generatedSpi, "REFERENCES_QUERY", String.class, "\"" + query + "\"", ObjectModelJavaModifier.PRIVATE);
ObjectModelOperation getReferenceQueryOperation = addOperation(generatedSpi, "getReferenceQuery", String.class, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, getReferenceQueryOperation, Override.class);
setOperationBody(getReferenceQueryOperation, ""+"\n"
+" return REFERENCES_QUERY;\n"
+" ");
}
}
private void generateConcreteSpi(String entityPackageName, String spiClassName, ObjectModelClass generatedSpi) {
if (getResourcesHelper().isJavaFileInClassPath(entityPackageName + "." + spiClassName)) {
return;
}
ObjectModelClass spi = createClass(spiClassName, entityPackageName);
setSuperClass(spi, generatedSpi.getQualifiedName());
}
protected Pair getParent(ToolkitEntityToDtoMapping entityToDtoMapping, ObjectModelClass input, TopiaMetadataEntity entity, Class> dtoDtoType, boolean entryPoint) {
if (entryPoint) {
return null;
}
String dtoTypeName = dtoDtoType.getName().replace("fr.ird.observe.dto.", "").replace("Dto", "");
for (ParentLink entry : parentProjectModel.getLinks()) {
String type = entry.getClassName();
if (dtoTypeName.equals(type)) {
TreeNodeModel node = navigationProjectModel.getNode(type).orElse(null);
if (node == null) {
break;
}
return Pair.of(entry.getPropertyName(), "fr.ird.observe.entities." + entry.getParentClassName());
}
}
// parent not found from navigation parent model
// possible since not all data are in navigation model
// must be DataDto, InlineDto, SimpleDto or ContainerDto
@SuppressWarnings("unchecked") Class extends DataDto> mainDtoType = entityToDtoMapping.getMainDtoType((Class extends DataDto>) dtoDtoType);
if (!Objects.equals(mainDtoType, dtoDtoType)) {
Pair parent = getParent(entityToDtoMapping, input, entity, mainDtoType, false);
if (parent != null) {
return parent;
}
}
Set oneToManyAssociationInverses = entity.getOneToManyAssociationInverses();
if (oneToManyAssociationInverses.size() == 1) {
String parent = oneToManyAssociationInverses.iterator().next();
TopiaMetadataEntity parentEntity = metadataModel.getEntity(parent);
Map manyToOneAssociations = parentEntity.getManyToOneAssociations();
Map oneToManyAssociations = parentEntity.getOneToManyAssociations();
String parentPropertyName = null;
if (manyToOneAssociations.containsValue(entity.getType())) {
parentPropertyName = manyToOneAssociations.entrySet().stream().filter(e -> entity.getType().equals(e.getValue())).findFirst().map(Map.Entry::getKey).orElse(null);
} else if (oneToManyAssociations.containsValue(entity.getType())) {
parentPropertyName = oneToManyAssociations.entrySet().stream().filter(e -> entity.getType().equals(e.getValue())).findFirst().map(Map.Entry::getKey).orElse(null);
}
return Pair.of(parentPropertyName, parentEntity.getFullyQualifiedName());
}
throw new IllegalStateException("Need to find parent for: " + dtoDtoType.getName());
}
private Class> guessSpiSuperClass(Class> dtoDtoType) {
if (OpenableDto.class.isAssignableFrom(dtoDtoType)) {
return OpenableDtoEntityContext.class;
}
if (EditableDto.class.isAssignableFrom(dtoDtoType)) {
return EditableDtoEntityContext.class;
}
if (SimpleDto.class.isAssignableFrom(dtoDtoType)) {
return SimpleDtoEntityContext.class;
}
if (ContainerDto.class.isAssignableFrom(dtoDtoType)) {
return ContainerDtoEntityContext.class;
}
return DataDtoEntityContext.class;
}
@SuppressWarnings("unused")
private void addFilterMethods(ObjectModelClass input, ObjectModelClass generatedSpi, boolean referential, boolean addGroupBy) {
ImportsManager importManager = getImportManager(generatedSpi);
ObjectModelPackage aPackage = model.getPackage(input);
String inputSimpleName = input.getName();
importManager.addExcludedPattern(".+\\." + inputSimpleName);
addImport(generatedSpi, IdFilterProperty.class);
addImport(generatedSpi, LongFilterProperty.class);
addImport(generatedSpi, TimestampFilterProperty.class);
StringBuilder filterContent = new StringBuilder(""+"\n"
+" List.of(\n"
+" IdFilterProperty.create(),\n"
+" LongFilterProperty.createPrimitive("+inputSimpleName+".PROPERTY_TOPIA_VERSION),\n"
+" TimestampFilterProperty.create("+inputSimpleName+".PROPERTY_TOPIA_CREATE_DATE),");
StringBuilder naturalOrderContent = new StringBuilder(""+"\n"
+" List.of(\n"
+"");
String[] naturalOrder = toolkitTagValues.getNaturalOrderTagValue(input);
if (naturalOrder == null) {
if (referential) {
naturalOrder = new String[]{ReferentialEntity.PROPERTY_CODE};
} else {
naturalOrder = new String[]{TopiaEntity.PROPERTY_TOPIA_CREATE_DATE};
}
}
List order = new LinkedList<>();
for (String s : naturalOrder) {
String constantName = getConstantName(s);
order.add(" " + inputSimpleName + "." + constantName);
}
naturalOrderContent.append(String.join(",\n", order)).append(""+"\n"
+" )");
Collection attributes = new LinkedList<>(input.getAttributes());
attributes.addAll(input.getAllOtherAttributes());
attributes.removeIf(a -> !a.isNavigable());
attributes.removeIf(GeneratorUtil::isNMultiplicity);
Map orderedAttributes = new TreeMap<>();
for (ObjectModelAttribute attribute : attributes) {
String attrName = GeneratorUtil.getSimpleName(getPropertyName(attribute));
orderedAttributes.put(attrName, attribute);
}
for (Map.Entry entry : orderedAttributes.entrySet()) {
String attrName = entry.getKey();
ObjectModelAttribute attribute = entry.getValue();
String attrType = getPropertyType(attribute, input, aPackage);
attrType = GeneratorUtil.removeAnyGenericDefinition(attrType);
if (entityClassesFully.contains(attrType)) {
if (attrType.contains(".referential.")) {
addReferentialFilterProperty(inputSimpleName, filterContent, attrName);
continue;
}
addDataFilterProperty(inputSimpleName, filterContent, attrName);
continue;
}
ObjectModelEnumeration enumeration = model.getEnumeration(attrType);
if (enumeration != null) {
addImport(generatedSpi, EnumFilterProperty.class);
addEnumFilterProperty(generatedSpi, inputSimpleName, filterContent, attrName, enumeration);
continue;
}
attrType = GeneratorUtil.getSimpleName(attrType);
switch (attrType) {
case "String":
addImport(generatedSpi, StringFilterProperty.class);
addStringFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "boolean":
addImport(generatedSpi, BooleanFilterProperty.class);
addPrimitiveBooleanFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Boolean":
addImport(generatedSpi, BooleanFilterProperty.class);
addBooleanFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "int":
addImport(generatedSpi, IntegerFilterProperty.class);
addPrimitiveIntegerFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "long":
addPrimitiveLongFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "float":
addImport(generatedSpi, FloatFilterProperty.class);
addPrimitiveFloatFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "double":
addImport(generatedSpi, IntegerFilterProperty.class);
addPrimitiveDoubleFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Integer":
addImport(generatedSpi, IntegerFilterProperty.class);
addIntegerFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Long":
addLongFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Float":
addImport(generatedSpi, FloatFilterProperty.class);
addFloatFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Double":
addImport(generatedSpi, DoubleFilterProperty.class);
addDoubleFilterProperty(inputSimpleName, filterContent, attrName);
continue;
case "Date":
String type = topiaHibernateTagValues.getHibernateAttributeType(attribute, input, aPackage, model);
if (type == null) {
type = "timestamp";
}
switch (type) {
case "date":
addImport(generatedSpi, DateFilterProperty.class);
addDateFilterProperty(inputSimpleName, filterContent, attrName);
break;
case "time":
addImport(generatedSpi, TimeFilterProperty.class);
addTimeFilterProperty(inputSimpleName, filterContent, attrName);
break;
case "timestamp":
addTimestampFilterProperty(inputSimpleName, filterContent, attrName);
break;
}
continue;
}
getLog().warn(String.format("No filter on %s.%s", inputSimpleName, attrName));
}
String content = filterContent.toString();
if (content.endsWith(",")) {
content = content.substring(0, content.length() - 1);
}
content += ""+"\n"
+" )";
addImport(generatedSpi, List.class);
addImport(generatedSpi, ImmutableMap.class);
addImport(generatedSpi, Map.class);
addImport(generatedSpi, Set.class);
addImport(generatedSpi, EntityFilterProperty.class);
addImport(generatedSpi, EntityFilterConsumer.class);
addAttribute(generatedSpi, "FILTER_PROPERTIES", "java.util.List>", content,
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
if (addGroupBy) {
if (entityClassesEntryPoints.contains(input.getQualifiedName())) {
String[] groupByList = topiaExtensionTagValues.getGroupBy(input);
if (groupByList != null) {
StringBuilder groupByContent = new StringBuilder(""+"\n"
+" List.>of(");
List tmp = new LinkedList<>();
for (String groupByPattern : groupByList) {
String groupBy = groupByPattern;
String groupBySecond = null;
int index = groupByPattern.indexOf(":");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
} else {
index = groupByPattern.indexOf(".");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
groupBySecond = groupByPattern.substring(index + 1);
}
}
String pair = addGroupBy(input, groupBy, groupBySecond);
tmp.add(",\n " + pair);
}
groupByContent.append(String.join("", tmp).substring(1)).append(""+"\n"
+" ).stream().collect(Collectors.toMap(DataGroupByEntityDefinition::getName, definition -> definition, (a, b) -> b, LinkedHashMap::new))");
addImport(generatedSpi, DataGroupByEntityDefinition.class);
addImport(generatedSpi, List.class);
addImport(generatedSpi, LinkedHashMap.class);
addImport(generatedSpi, Collectors.class);
addImport(generatedSpi, Function.class);
String type = String.format("Map>", inputSimpleName);
addAttribute(generatedSpi, "FILTER_GROUP_BY", type, groupByContent.toString(),
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
ObjectModelOperation getGroupBy = addOperation(generatedSpi, "getGroupBy", type,
ObjectModelJavaModifier.PUBLIC,
ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, getGroupBy, Override.class);
setOperationBody(getGroupBy, ""+"\n"
+" return FILTER_GROUP_BY;\n"
+" ");
groupByDtoDefinitionMapping.add(input.getQualifiedName() + ".SPI");
}
}
}
addAttribute(generatedSpi, "FILTER_AUTHORIZED_PROPERTIES", "java.util.Set", "EntityFilterConsumer.getAuthorizedPropertyNames(FILTER_PROPERTIES)",
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
addAttribute(generatedSpi, "FILTER_AUTHORIZED_ORDERS", "java.util.Set", "EntityFilterConsumer.getAuthorizedOrders(FILTER_PROPERTIES)",
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
addAttribute(generatedSpi, "FILTER_PROPERTIES_CONSUMERS", "Map>", "EntityFilterConsumer.getPropertyConsumers(FILTER_PROPERTIES)",
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
addAttribute(generatedSpi, "FILTER_NATURAL_ORDERS", "java.util.List", naturalOrderContent.toString(),
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.PRIVATE,
ObjectModelJavaModifier.STATIC);
{
ObjectModelOperation newFilterConsumer = addOperation(generatedSpi, "newFilterConsumer", "EntityFilterConsumer<" + inputSimpleName + ">",
ObjectModelJavaModifier.PUBLIC,
ObjectModelJavaModifier.FINAL);
addParameter(newFilterConsumer, ReferentialLocale.class, "referentialLocale");
addAnnotation(generatedSpi, newFilterConsumer, Override.class);
addImport(generatedSpi, Objects.class);
setOperationBody(newFilterConsumer, ""+"\n"
+" return new EntityFilterConsumer<>(Objects.requireNonNull(referentialLocale.getColumnName()), FILTER_PROPERTIES, FILTER_AUTHORIZED_PROPERTIES, FILTER_AUTHORIZED_ORDERS, FILTER_NATURAL_ORDERS, FILTER_PROPERTIES_CONSUMERS);\n"
+" ");
}
ObjectModelOperation getNaturalOrder = addOperation(generatedSpi, "getNaturalOrder", "List",
ObjectModelJavaModifier.PUBLIC,
ObjectModelJavaModifier.FINAL);
addAnnotation(generatedSpi, getNaturalOrder, Override.class);
setOperationBody(getNaturalOrder, ""+"\n"
+" return FILTER_NATURAL_ORDERS;\n"
+" ");
}
private void addEnumFilterProperty(ObjectModelClass generatedSpi, String inputSimpleName, StringBuilder filterContent, String attrName, ObjectModelEnumeration attrType) {
addImport(generatedSpi, attrType.getQualifiedName());
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" EnumFilterProperty.create("+propertyName+", "+attrType.getName()+".class),");
}
private void addIntegerFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" IntegerFilterProperty.create("+propertyName+"),");
}
private void addLongFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" LongFilterProperty.create("+propertyName+"),");
}
private void addFloatFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" FloatFilterProperty.create("+propertyName+"),");
}
private void addDoubleFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" DoubleFilterProperty.create("+propertyName+"),");
}
private void addPrimitiveIntegerFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" IntegerFilterProperty.createPrimitive("+propertyName+"),");
}
private void addPrimitiveLongFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" LongFilterProperty.createPrimitive("+propertyName+"),");
}
private void addPrimitiveFloatFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" FloatFilterProperty.createPrimitive("+propertyName+"),");
}
private void addPrimitiveDoubleFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" FilterProperty.createPrimitive("+propertyName+"),");
}
private void addStringFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" StringFilterProperty.create("+propertyName+"),");
}
private void addPrimitiveBooleanFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" BooleanFilterProperty.createPrimitive("+propertyName+"),");
}
private void addBooleanFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" BooleanFilterProperty.create("+propertyName+"),");
}
private void addDateFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" DateFilterProperty.create("+propertyName+"),");
}
private void addTimeFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" TimeFilterProperty.create("+propertyName+"),");
}
private void addTimestampFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" TimestampFilterProperty.create("+propertyName+"),");
}
private void addReferentialFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" IdFilterProperty.create("+propertyName+"),\n"
+" StringFilterProperty.createCode("+propertyName+"),\n"
+" StringFilterProperty.createLabel("+propertyName+"),");
}
private void addDataFilterProperty(String inputSimpleName, StringBuilder filterContent, String attrName) {
String constantName = getConstantName(attrName);
String propertyName = inputSimpleName + "." + constantName;
filterContent.append(""+"\n"
+" IdFilterProperty.create("+propertyName+"),");
}
protected String generateMainSpi(Class> dtoDtoType, String entityPackageName, String entityName, String constantType) {
String constantName = "SPI";
addAttribute(outputInterface, constantName, constantType, "new " + constantType + "()");
entityToDtoClassMapping.put(entityPackageName + "." + entityName, dtoDtoType.getName() + ".class");
entityToDtoClassMapping.put(entityPackageName + "." + entityName + "Impl", dtoDtoType.getName() + ".class");
return entityPackageName + "." + entityName + "." + constantName;
}
protected String generateSubSpi(Class> dtoDtoType, String entityPackageName, String entityName, String constantType) {
String constantName = builder.getConstantName(ProjectPackagesDefinition.cleanType(dtoDtoType.getSimpleName()).replaceAll("\\.", "_") + "_spi");
addAttribute(outputInterface, constantName, constantType, "new " + constantType + "()");
return entityPackageName + "." + entityName + "." + constantName;
}
@SuppressWarnings({"unused"})
@Override
protected void createEntityAbstractClass(ObjectModelPackage aPackage, ObjectModelClass input) {
boolean isAbstract = input.isAbstract() && !input.isStatic();
if (doDto && isAbstract) {
outputAbstract = createAbstractClass(String.format("%s", input.getName() + "Abstract", dtoContractType.getName(), referenceContractType.getName()), input.getPackageName());
addImport(outputAbstract, dtoContractType);
addImport(outputAbstract, referenceContractType);
} else {
outputAbstract = createAbstractClass(input.getName() + "Abstract", input.getPackageName());
}
addImport(outputAbstract, input.getQualifiedName());
// Documentation
StringBuilder doc = new StringBuilder();
doc.append("Implantation POJO pour l'entité {@link ");
doc.append(Strings.capitalize(input.getName()));
doc.append("}\n");
String dbName = templateHelper.getDbName(input);
if (dbName != null) {
doc.append("Nom de l'entité en BD : ");
doc.append(dbName);
doc.append(".
");
}
setDocumentation(outputAbstract, doc.toString());
boolean isDataEntity = DataEntity.class.getSimpleName().equals(input.getName()) || ReferentialEntity.class.getSimpleName().equals(input.getName());
if (doDto) {
if (isAbstract) {
addImport(outputAbstract, parentWithGeneric + "Impl");
addImport(outputAbstract, parentWithGeneric);
setSuperClass(outputAbstract, parentWithGeneric + "Impl");
addInterface(outputAbstract, input.getQualifiedName());
} else {
addImport(outputAbstract, parentWithGeneric);
setSuperClass(outputAbstract, parentWithGeneric + "Impl");
addInterface(outputAbstract, parentWithGeneric);
addInterface(outputAbstract, input.getQualifiedName());
}
} else {
// Implements
addInterface(outputAbstract, input.getQualifiedName());
// Extends
for (ObjectModelClass parent : input.getSuperclasses()) {
//tchemit-2011-09-12 What ever abstract or not, we always use an Impl, moreover use the util method instead
String extendClass = templateHelper.getDOType(parent, model);
setSuperClass(outputAbstract, extendClass);
}
// Extends AbstractTopiaEntity (only if hasn't parent entity)
if (outputAbstract.getSuperclasses().isEmpty()) {
String superClassName = topiaCoreTagValues.getEntitySuperClassTagValue(input, aPackage, model);
if (superClassName == null) {
superClassName = AbstractTopiaEntity.class.getName();
}
setSuperClass(outputAbstract, superClassName);
}
}
// add statistics
if (doDto && statisticDefinitions != null) {
String packageName = dtoType.getPackageName();
StatisticsHelper.addWithStatistics(this, packageName, input, outputAbstract, outputInterface, statisticDefinitions);
}
}
@Override
protected void generateImpl(ObjectModelClass input) {
String implName = input.getName() + "Impl";
String packageName = input.getPackageName();
if (isVerbose()) {
log.info("Will generate [" + implName + "]");
}
boolean isAbstract = isAbstract(input) && !input.isStatic();
if (isAbstract) {
outputImpl = createAbstractClass(implName, packageName);
setSuperClass(outputImpl, input.getQualifiedName() + "Abstract");
} else {
outputImpl = createClass(implName, packageName);
setSuperClass(outputImpl, input.getQualifiedName() + "Abstract");
}
setDocumentation(outputImpl, String.format("Implantation des operations pour l'entité %s.", input.getName()));
}
@Override
protected void generateProperties(Collection attributes, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
boolean withParentId = aClass.getInterfaces().stream().anyMatch(i -> i.getQualifiedName().equals(DtoParentAware.class.getName()));
if (withParentId) {
ObjectModelAttributeImpl e = new ObjectModelAttributeImpl();
e.setName("parentId");
e.setType(String.class.getName());
e.setObjectModelImpl((ObjectModelImpl) model);
e.setReverseAttributeName("nope");
e.postInit();
attributes = new LinkedList<>(attributes);
attributes.add(e);
}
super.generateProperties(attributes, aClass, aPackage);
}
@Override
protected void addSingleGetOperation(ObjectModelClass input, ObjectModelAttribute attribute, String attrType, String operationPrefix) {
super.addSingleGetOperation(input, attribute, attrType, operationPrefix);
boolean entity = templateHelper.isEntity(attribute, model);
if (entity) {
// add getXXXSize method (return 0 if no value, 1 if with value)
addSingleSizeOperation(attribute);
}
}
protected void addSingleSizeOperation(ObjectModelAttribute attribute) {
String attrName = getPropertyName(attribute);
log.debug(String.format("Generate single 'getSize' operation for property : %s", attrName));
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("get", attrName + "Size"),
int.class, ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
String getter = getJavaBeanMethodName("get", attrName);
setOperationBody(implOperation, ""+"\n"
+" return "+getter+"() == null ? 0 : 1;\n"
+" ");
}
@Override
public ObjectModelOperation addOperation(ObjectModelClassifier classifier, String name, String type, ObjectModelModifier... modifiers) {
if (entityClasses != null && !type.startsWith(getDefaultPackageName())) {
String type1 = GeneratorUtil.removeAnyGenericDefinition(GeneratorUtil.getSimpleName(type, true));
if (!entityClasses.contains(type1)) {
Set types = GeneratorUtil.getTypesList(type);
boolean doIt = true;
for (String s : types) {
String s1 = GeneratorUtil.getSimpleName(s);
if (entityClasses.contains(s1)) {
doIt = false;
break;
}
}
if (doIt) {
addImport(classifier, type);
type = GeneratorUtil.getSimpleName(type);
}
}
}
return super.addOperation(classifier, name, type, modifiers);
}
@Override
public ObjectModelParameter addParameter(ObjectModelOperation operation, String type, String name) {
if (!type.startsWith(getDefaultPackageName())) {
String type1 = GeneratorUtil.removeAnyGenericDefinition(GeneratorUtil.getSimpleName(type, true));
ObjectModelClassifier declaringElement = (ObjectModelClassifier) operation.getDeclaringElement();
if (!entityClasses.contains(type1)) {
Set types = GeneratorUtil.getTypesList(type);
boolean doIt = true;
for (String s : types) {
String s1 = GeneratorUtil.getSimpleName(s);
if (entityClasses.contains(s1)) {
doIt = false;
break;
}
}
if (doIt) {
addImport(declaringElement, type);
type = GeneratorUtil.getSimpleName(type);
}
}
}
return super.addParameter(operation, type, name);
}
String addGroupBy(ObjectModelClass input, String groupBy, String groupBySecond) {
ObjectModelAttribute parentAttribute = Objects.requireNonNull(input.getAttribute(groupBy));
boolean mandatory = validationTagValues.isNotNull(model.getTagValuesStore(), input, parentAttribute);
ObjectModelClassifier classifier = parentAttribute.getClassifier();
if (classifier instanceof ObjectModelClass && entityClassesFully.contains(classifier.getQualifiedName())) {
if (groupBySecond == null) {
return addGroupBy(input, groupBy, null, classifier.getQualifiedName(), mandatory, null);
} else {
ObjectModelAttribute secondClassifierAttribute = classifier.getAttribute(groupBySecond);
ObjectModelClass secondClassifier = model.getClass(classifier.getQualifiedName());
return addGroupBy(input, groupBy, groupBySecond, secondClassifierAttribute.getClassifier().getQualifiedName(), mandatory, secondClassifier);
}
}
return addGroupBy(input, groupBy, null, parentAttribute.getType(), mandatory, null);
}
private String addGroupBy(ObjectModelClass input, String groupByPropertyName, String groupBySecond, String type, boolean mandatory, ObjectModelClass secondClassifier) {
String capitalize = Strings.capitalize(groupByPropertyName);
if (groupBySecond != null) {
capitalize += Strings.capitalize(groupBySecond);
}
String inputName = input.getName();
String formClassName = inputName + "GroupBy" + capitalize;
String definitionClassName = formClassName + "Definition";
String spiClassName = formClassName + "Spi";
String dtoType = entityToDtoClassMapping.get(input.getQualifiedName()).replace(".class", "");
String dtoDefinitionClassName = dtoType.replace("." + GeneratorUtil.getSimpleName(dtoType), "." + formClassName + "DtoDefinition");
String dtoFormClassName = dtoType.replace("." + GeneratorUtil.getSimpleName(dtoType), "." + formClassName + "Dto");
String simplifyGroupType = GeneratorUtil.getSimpleName(type);
// generate Definition
ObjectModelClass definitionClass = createClass(definitionClassName, input.getPackageName());
addImport(definitionClass, type);
addImport(definitionClass, dtoType);
addImport(definitionClass, Strings.class);
addImport(definitionClass, dtoFormClassName);
addImport(definitionClass, dtoType.replace("Dto", "Reference"));
String businessProject = "fr.ird.observe.spi.module.ObserveBusinessProject";
String moduleName = ProjectPackagesDefinition.extractFirstPackage(ProjectPackagesDefinition.removeFirstPackage(input.getPackageName().replace(getDefaultPackageName() + ".", "")));
String moduleMethodName = String.format("() -> %s.get().get%sBusinessModule()", importAndSimplify(definitionClass, businessProject), Strings.capitalize(moduleName));
setSuperClass(definitionClass, String.format("%1$s<%2$s, %3$s, %4$s, %5$s>", DataGroupByEntityDefinition.class.getName(), inputName, formClassName, dtoType, dtoFormClassName));
String definitionId = Introspector.decapitalize(TreeProjectModelBuilder.toCamelCase(input.getQualifiedName().substring(getDefaultPackageName().length()) + ".groupBy." + groupByPropertyName));
if (groupBySecond != null) {
definitionId += Strings.capitalize(groupBySecond);
}
addConstant(definitionClass, "NAME", "String", "\"" + definitionId + "\"", ObjectModelJavaModifier.PUBLIC);
DataGroupByType groupByType = model.getClassifier(type) == null ? DataGroupByType.TEMPORAL : DataGroupByType.QUALITATIVE;
addImport(definitionClass, DataGroupByType.class);
ObjectModelOperation definitionConstructor = addConstructor(definitionClass, ObjectModelJavaModifier.PACKAGE);
String constantName = inputName + "." + getConstantName(groupByPropertyName);
String groupBySecondTable = null;
if (groupBySecond != null) {
constantName += " + \".\" + " + secondClassifier.getQualifiedName() + "." + getConstantName(groupBySecond);
groupBySecondTable = "\"" + metadataModel.getEntity(templateHelper.getEntityEnumLiteralName(secondClassifier)).getSchemaAndTableName() + "\"";
}
setOperationBody(definitionConstructor, ""+"\n"
+" super(NAME, DataGroupByType."+groupByType+", "+constantName+", "+mandatory+", "+simplifyGroupType+".class, "+inputName+".class, "+formClassName+".class, "+formClassName+"::new, "+moduleMethodName+", "+groupBySecondTable+");\n"
+" ");
ObjectModelOperation dtoDefinitionOperation = addOperation(definitionClass, "dtoDefinition", dtoDefinitionClassName, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(definitionClass, dtoDefinitionOperation, Override.class);
setOperationBody(dtoDefinitionOperation, ""+"\n"
+" return "+dtoFormClassName+".DEFINITION;\n"
+" ");
ObjectModelOperation toGroupByValueOperation = addOperation(definitionClass, "toGroupByObjectValue", type, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addParameter(toGroupByValueOperation, inputName, "data");
addAnnotation(definitionClass, toGroupByValueOperation, Override.class);
String getterName = getJavaBeanMethodName("get", groupByPropertyName);
if (groupBySecond != null) {
getterName += "()." + getJavaBeanMethodName("get", groupBySecond);
}
setOperationBody(toGroupByValueOperation, ""+"\n"
+" return data."+getterName+"();\n"
+" ");
ObjectModelOperation setGroupByValueOperation = addOperation(definitionClass, "setGroupByValue", void.class, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addParameter(setGroupByValueOperation, inputName, "data");
addParameter(setGroupByValueOperation, Object.class, "value");
addAnnotation(definitionClass, setGroupByValueOperation, Override.class);
if (groupBySecond == null) {
String setterName = getJavaBeanMethodName("set", groupByPropertyName);
setOperationBody(setGroupByValueOperation, ""+"\n"
+" data."+setterName+"(("+type+") value);\n"
+" ");
} else {
setOperationBody(setGroupByValueOperation, ""+"\n"
+" ");
}
// generate Entity
ObjectModelClass entityClass = createClass(formClassName, input.getPackageName());
{
addImport(entityClass, DataGroupByEntityDefinition.class);
addImport(entityClass, type);
addImport(entityClass, dtoType);
addImport(entityClass, dtoType.replace("Dto", "Reference"));
setSuperClass(entityClass, String.format("%1$s<%2$s>", DataGroupByEntityAbstract.class.getName(), inputName));
addConstant(entityClass, "DEFINITION", definitionClassName, String.format("new %1$s()", definitionClassName), ObjectModelJavaModifier.PUBLIC);
ObjectModelOperation definitionOperation = addOperation(entityClass, "definition", definitionClassName, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL);
addAnnotation(entityClass, definitionOperation, Override.class);
setOperationBody(definitionOperation, ""+"\n"
+" return DEFINITION;\n"
+" ");
addContractTypeMethod(input, entityClass);
}
return entityClass.getQualifiedName() + ".DEFINITION";
}
@Override
protected void clean() {
super.clean();
dtoContractType = dtoType = null;
referenceContractType = referenceType = null;
parentWithGeneric = null;
doDto = doReference = false;
}
private String getTypeGenericBounds(Type type, String daoName) {
Set typeVariables = null;
if (type instanceof TypeVariable) {
TypeVariable> type1 = (TypeVariable>) type;
typeVariables = Arrays.stream(type1.getGenericDeclaration().getTypeParameters()).map(TypeVariable::getName).collect(Collectors.toCollection(TreeSet::new));
} else if (type instanceof ParameterizedType) {
ParameterizedType type1 = (ParameterizedType) type;
typeVariables = Arrays.stream(type1.getActualTypeArguments()).map(Type::getTypeName).collect(Collectors.toCollection(TreeSet::new));
}
String returnType = type.getTypeName();
if (typeVariables != null) {
List typesList = new ArrayList<>(GeneratorUtil.getTypesList(returnType));
for (String typeVariable : typeVariables) {
if (Objects.equals(returnType, typeVariable.trim())) {
switch (typeVariable) {
case "D":
return dtoType.getName();
case "R":
return referenceType.getName();
case "T":
return daoName;
case "E":
return outputInterface.getQualifiedName();
}
}
if (typesList.contains(typeVariable)) {
switch (typeVariable) {
case "D":
returnType = replaceType(returnType, typesList, typeVariable, dtoType.getName());
break;
case "R":
returnType = replaceType(returnType, typesList, typeVariable, (doReference ? referenceType.getName() : "?"));
break;
case "T":
returnType = replaceType(returnType, typesList, typeVariable, daoName);
break;
case "E":
returnType = replaceType(returnType, typesList, typeVariable, outputInterface.getQualifiedName());
break;
}
}
}
}
return returnType;
}
private String replaceType(String returnType, List typesList, String typeVariable, String name) {
StringBuilder result = new StringBuilder(returnType.substring(0, returnType.indexOf('<') + 1));
Iterator restingParts = Arrays.asList(returnType.trim().substring(result.length(), returnType.length() - 1).split("\\s*,\\s*")).iterator();
while (restingParts.hasNext()) {
String restingPart = restingParts.next();
if (restingPart.trim().equals(typeVariable)) {
result.append(name);
typesList.remove(typeVariable);
} else {
result.append(restingPart);
}
if (restingParts.hasNext()) {
result.append(" ,");
}
}
result.append(">");
return result.toString();
}
private void generateJavaBeanMethods() {
// add JavaBeanDefinition constant
addImport(outputInterface, JavaBeanDefinition.class);
addImport(outputInterface, JavaBeanDefinitionStore.class);
addImport(outputInterface, IllegalStateException.class);
addConstant(outputInterface, "JAVA_BEAN_DEFINITION", JavaBeanDefinition.class.getSimpleName(), String.format("JavaBeanDefinitionStore.getDefinition(%s.class).orElseThrow(IllegalStateException::new)", outputInterface.getName()), ObjectModelJavaModifier.PUBLIC);
// add JavaBean method
ObjectModelOperation operation = addOperation(outputInterface, "javaBeanDefinition", JavaBeanDefinition.class.getSimpleName(), ObjectModelJavaModifier.DEFAULT);
setOperationBody(operation, ""+"\n"
+" return JAVA_BEAN_DEFINITION;\n"
+" ");
addAnnotation(outputInterface, operation, Override.class);
}
private void generateSpiDelegateMethods(boolean referential, String daoName) {
List methods = Arrays.stream((referential ? ReferentialDtoEntityContext.class : DataDtoEntityContext.class).getMethods()).filter(method -> {
int modifiers = method.getModifiers();
if (Modifier.isStatic(modifiers) || method.isSynthetic()) {
return false;
}
String methodName = method.getName();
return spiMethodNames.contains(methodName);
}).collect(Collectors.toList());
for (Method method : methods) {
String methodName = method.getName();
String returnType = getTypeGenericBounds(method.getGenericReturnType(), daoName);
addImport(outputInterface, returnType);
ObjectModelOperation operation = addOperation(outputInterface, methodName, returnType, ObjectModelJavaModifier.STATIC);
for (Parameter parameter : method.getParameters()) {
String parameterName = parameter.getName();
String parameterType = getTypeGenericBounds(parameter.getParameterizedType(), daoName);
addImport(outputInterface, parameterType);
addParameter(operation, parameterType, parameterName);
}
StringBuilder content = new StringBuilder();
if (void.class.equals(method.getReturnType())) {
content.append(""+"\n"
+" "
);
} else {
content.append(""+"\n"
+" return"
);
}
content.append(""+" SPI."+methodName+"("
);
Iterator iterator = Arrays.asList(method.getParameters()).iterator();
while (iterator.hasNext()) {
Parameter parameter = iterator.next();
@SuppressWarnings("unused") String parameterName = parameter.getName();
content.append(""+""+parameterName+""
);
if (iterator.hasNext()) {
content.append(""+", "
);
}
}
content.append(""+");\n"
+" "
);
setOperationBody(operation, content.toString());
}
}
private Set collectAllInterfaces(ObjectModelClassifier classifier) {
Set result = new LinkedHashSet<>();
collectAllInterfaces(classifier, false, result);
return result;
}
private void collectAllInterfaces(ObjectModelClassifier classifier, boolean collectSuperClasses, Set result) {
if (collectSuperClasses && classifier instanceof ObjectModelClass) {
ObjectModelClass classifier1 = (ObjectModelClass) classifier;
for (ObjectModelClass superclass : classifier1.getSuperclasses()) {
result.add(superclass.getQualifiedName());
collectAllInterfaces(superclass, true, result);
}
}
for (ObjectModelInterface anInterface : classifier.getInterfaces()) {
result.add(anInterface.getQualifiedName());
ObjectModelClassifier classifier1 = model.getClassifier(anInterface.getQualifiedName());
if (classifier1 != null) {
collectAllInterfaces(classifier1, true, result);
}
}
}
protected void addInterface(List interfaceAlreadyDone,
ObjectModelClassifier output,
String qualifiedName) {
if (!interfaceAlreadyDone.contains(qualifiedName)) {
// add it to output
addInterface(output, qualifiedName);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy