org.nuiton.topia.templates.EntityTransformer Maven / Gradle / Ivy
package org.nuiton.topia.templates;
/*
* #%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 io.ultreia.java4all.classmapping.ImmutableClassMapping;
import io.ultreia.java4all.lang.Numbers;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.EugeneCoreTagValues;
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.ObjectModelAssociationClass;
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.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.ObjectModelInterfaceImpl;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityVisitor;
import org.nuiton.topia.persistence.TopiaException;
import org.nuiton.topia.persistence.internal.AbstractTopiaEntity;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntity;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModel;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataOneToOneComposition;
import org.nuiton.topia.templates.sql.TopiaMetadataModelBuilder;
import java.io.File;
import java.io.IOException;
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.ServiceLoader;
import java.util.Set;
/**
* 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", "unused", "UnusedAssignment", "SameParameterValue"})
@Component(role = Template.class, hint = "org.nuiton.topia.templates.EntityTransformer")
public class EntityTransformer extends ObjectModelTransformerToJava {
private static final Logger log = LogManager.getLogger(EntityTransformer.class);
protected final TopiaCoreTagValues topiaCoreTagValues;
protected final TopiaExtensionTagValues topiaExtensionTagValues;
protected final TopiaHibernateTagValues topiaHibernateTagValues;
protected ObjectModelInterface outputInterface;
protected ObjectModelClass outputAbstract;
protected ObjectModelClass outputImpl;
protected boolean generateInterface;
protected boolean generateAbstract;
protected boolean generateImpl;
protected boolean generateBooleanGetMethods;
protected boolean generatePropertyChangeSupport;
protected TopiaTemplateHelper templateHelper;
protected EntityToDtoMapping entityToDtoMapping;
protected boolean doDto;
protected ObjectModelClass input;
private boolean associationClass;
private boolean useRelativeName;
private ObjectModelOperation internalAcceptOperation;
private Set> dtoTypes;
private StringBuilder internalAcceptOperationBody;
private Map, StringBuilder> spiToDtoOperationBody;
private Map, StringBuilder> spiFromDtoOperationBody;
protected TopiaMetadataModel metadataModel;
protected TopiaMetadataOneToOneComposition oneToOneComposition;
protected ObjectModelAttribute reverseOneToOneAttribute;
public EntityTransformer() {
this.topiaCoreTagValues = new TopiaCoreTagValues();
this.topiaHibernateTagValues = new TopiaHibernateTagValues();
this.topiaExtensionTagValues = new TopiaExtensionTagValues();
}
protected void clean() {
outputInterface = null;
outputAbstract = null;
outputImpl = null;
spiToDtoOperationBody = null;
spiFromDtoOperationBody = null;
input = null;
dtoTypes = null;
}
@Override
public void applyTemplate(ObjectModel model, File destDir) throws IOException {
templateHelper = new TopiaTemplateHelper(model);
metadataModel = TopiaMetadataModelBuilder.buildFull(isVerbose(), model, templateHelper);
super.applyTemplate(model, destDir);
}
@Override
public void transformFromModel(ObjectModel model) {
for (EntityToDtoMapping toDtoMapping : ServiceLoader.load(EntityToDtoMapping.class, getClassLoader())) {
this.entityToDtoMapping = toDtoMapping;
this.entityToDtoMapping.init(this);
break;
}
List entityClasses = templateHelper.getEntityClasses(model, true);
EugeneCoreTagValues coreTagValues = new EugeneCoreTagValues();
useRelativeName = coreTagValues.isUseRelativeName(model);
Set relativeNameExcludes = coreTagValues.getRelativeNameExcludes(model);
String[] relativeNameExcludes1 = relativeNameExcludes == null ? new String[0] : relativeNameExcludes.toArray(new String[0]);
super.transformFromModel(model);
}
@Override
protected void debugOutputModel() {
super.debugOutputModel();
if (entityToDtoMapping != null) {
entityToDtoMapping.close();
}
}
@Override
public void transformFromClass(ObjectModelClass input) {
if (!templateHelper.isEntity(input)) {
// not an entity, skip class.
return;
}
if (log.isDebugEnabled()) {
log.debug("for entity : " + input.getQualifiedName());
log.debug("Will use classLoader " + getClassLoader());
}
setDoDto(input);
ObjectModelPackage aPackage = getPackage(input);
// fix once for all the constant prefix to use
String prefix = getConstantPrefix(input);
if (StringUtils.isEmpty(prefix)) {
// no specific prefix, so no prefix
if (log.isWarnEnabled()) {
log.warn("[" + input.getName() + "] Will generate constants with NO prefix, not a good idea... \n" +
"Use '" + EugeneCoreTagValues.Store.constantPrefix +
"' tagvalue in your xmi properties. For example " +
"for all the model : model.tagvalue." + EugeneCoreTagValues.Store.constantPrefix + "=PROPERTY_");
}
}
setConstantPrefix(prefix);
generateInterface = isGenerateInterface(input);
generateAbstract = isGenerateAbstract(input);
generateImpl = isGenerateImpl(input);
generateBooleanGetMethods = eugeneTagValues.isGenerateBooleanGetMethods(input, aPackage, model);
generatePropertyChangeSupport = topiaCoreTagValues.isGeneratePropertyChangeSupport(input, model);
if (generateInterface) {
// Create Entity Interface and its header
createEntityInterface(aPackage, input);
} else {
// mock it
outputInterface = new ObjectModelInterfaceImpl();
((ObjectModelInterfaceImpl) outputInterface).setName(input.getName());
}
if (generateAbstract) {
// Create Entity Abstract class and its header
createEntityAbstractClass(aPackage, input);
}
// Generate i18n block
String i18nPrefix = eugeneTagValues.getI18nPrefixTagValue(input, aPackage, model);
if (!StringUtils.isEmpty(i18nPrefix)) {
generateI18nBlock(input, outputAbstract, i18nPrefix);
}
// Create accept operation, will be updated during property generation
createAcceptOperation();
createAcceptInternalOperation(input);
// Add constant, attribute and operations for each property
generateProperties(input.getAttributes(), input, aPackage);
// Case of association class : properties from participants/extremities
// of the association class.
if (input instanceof ObjectModelAssociationClass) {
ObjectModelAssociationClass association = (ObjectModelAssociationClass) input;
associationClass = true;
generateProperties(association.getParticipantsAttributes(), input, aPackage);
associationClass = false;
}
closeAcceptInternalOperation();
// Add extra constants (from uml dependency)
generateExtraConstants(input);
// Add extra operations (defined on the entity)
generateExtraOperations(input);
if (generateAbstract) {
// Generate serialVersionUID on abstract class
generateSerialVersionUID(input, outputAbstract);
}
if (generateImpl) {
// Generate Entity Implementation class
generateImpl(input);
generateSerialVersionUID(input, outputImpl);
}
// Clean data output after transformation
clean();
}
protected void setDoDto(ObjectModelClass input) {
this.input = input;
doDto = entityToDtoMapping != null && entityToDtoMapping.accept(input);
String literalName = templateHelper.getEntityEnumLiteralName(input);
TopiaMetadataEntity metadataEntity = metadataModel.getEntity(literalName);
Set oneToOneCompositions = metadataModel.getReverseOneToOneAssociations(literalName);
if (oneToOneCompositions != null && !oneToOneCompositions.isEmpty()) {
oneToOneComposition = oneToOneCompositions.iterator().next();
String oneToOneAttributeName = oneToOneComposition.getTargetPropertyName();
ObjectModelAttribute reverseOneToOneAttribute = null;
for (ObjectModelAttribute attribute : input.getAttributes()) {
if (!attribute.isNavigable()) {
reverseOneToOneAttribute = attribute.getReverseAttribute();
if (oneToOneAttributeName == null || reverseOneToOneAttribute == null || !Objects.equals(oneToOneAttributeName, reverseOneToOneAttribute.getName())) {
continue;
}
break;
}
}
this.reverseOneToOneAttribute = Objects.requireNonNull(reverseOneToOneAttribute);
} else {
oneToOneComposition = null;
this.reverseOneToOneAttribute = null;
}
}
protected void generateSerialVersionUID(ObjectModelClass input, ObjectModelClass output) {
addConstant(output, GeneratorUtil.SERIAL_VERSION_UID, long.class, "1L", ObjectModelJavaModifier.PRIVATE);
}
protected void createEntityInterface(ObjectModelPackage aPackage,
ObjectModelClass input) {
outputInterface = createInterface(input.getName(),
input.getPackageName());
addImport(outputInterface, outputInterface.getQualifiedName());
// Documentation
if (GeneratorUtil.hasDocumentation(input)) {
setDocumentation(outputInterface, input.getDocumentation());
}
List interfaceAlreadyDone = new LinkedList<>();
// Extends
for (ObjectModelClassifier parent : input.getInterfaces()) {
addInterface(interfaceAlreadyDone, outputInterface, parent);
}
// Extends from inheritance
boolean needTopiaEntity = true;
for (ObjectModelClassifier parent : input.getSuperclasses()) {
if (templateHelper.isEntity(parent)) {
addInterface(interfaceAlreadyDone, outputInterface, parent);
needTopiaEntity = false;
}
}
// Extends TopiaEntity (only if hasn't parent entity)
if (needTopiaEntity) {
addInterface(interfaceAlreadyDone, outputInterface, TopiaEntity.class);
}
addContractTypeMethod(input, outputInterface);
}
protected void createEntityAbstractClass(ObjectModelPackage aPackage,
ObjectModelClass input) {
outputAbstract = createAbstractClass(input.getName() + "Abstract",
input.getPackageName());
addImport(outputAbstract, outputInterface.getQualifiedName());
// Documentation
StringBuilder doc = new StringBuilder();
doc.append("Implantation POJO pour l'entité {@link ");
doc.append(StringUtils.capitalize(outputInterface.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());
// Implements
addInterface(outputAbstract, outputInterface.getName());
// 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);
}
}
protected boolean isGenerateInterface(ObjectModelClass input) {
return !getResourcesHelper().isJavaFileInClassPath(input.getQualifiedName());
}
protected boolean isGenerateAbstract(ObjectModelClass input) {
String fqn = input.getQualifiedName() + "Abstract";
return !getResourcesHelper().isJavaFileInClassPath(fqn);
}
protected boolean isGenerateImpl(ObjectModelClass input) {
Collection operations = input.getOperations();
String fqn = input.getQualifiedName() + "Impl";
boolean alreadyInClassPath = getResourcesHelper().isJavaFileInClassPath(fqn);
if (alreadyInClassPath) {
return false;
}
// On ne génère pas le impl si l'entité a des opérations
if (!operations.isEmpty()) {
log.info("Will not generate [" + fqn + "], there is some operations to manually implement");
return false;
}
//De même, on ne génère pas le impl si il y a des opérations venant des
// superclasses non implémentées
for (ObjectModelOperation otherOp : input.getAllOtherOperations(false)) {
if (otherOp.isAbstract()) {
log.info("Will not generate [" + fqn + "], there is an abstract operation [" + otherOp.getName() + "] in allOtherOperations.");
return false;
}
}
return true;
}
protected void generateImpl(ObjectModelClass input) {
String implName = input.getName() + "Impl";
String packageName = input.getPackageName();
if (isVerbose()) {
log.info("Will generate [" + implName + "]");
}
if (isAbstract(input)) {
outputImpl = createAbstractClass(implName, packageName);
} else {
outputImpl = createClass(implName, packageName);
}
setDocumentation(outputImpl, "Implantation des operations pour l'entité " +
input.getName() + ".");
setSuperClass(outputImpl, input.getQualifiedName() + "Abstract");
}
/**
* Generate extra constants if {@code input} has dependencies on
* enum used as constant injector.
*
* @param input Entity class to treate
*/
protected void generateExtraConstants(ObjectModelClass input) {
Set constants = addConstantsFromDependency(input, outputInterface);
if (log.isDebugEnabled()) {
log.debug("Add constants from dependency : " + constants);
}
}
protected void generateExtraOperations(ObjectModelClass input) {
for (ObjectModelOperation operation : input.getOperations()) {
String opName = operation.getName();
String opType = operation.getReturnType();
ObjectModelModifier visibility =
ObjectModelJavaModifier.fromVisibility(operation.getVisibility());
if (log.isDebugEnabled()) {
log.debug("Extra operation for : " + input.getQualifiedName() +
" - method : " + opName +
" - returnType : " + opType +
" - visibility : " + visibility);
}
// Generate entity methods which have not a public visibility.
// Only in abstract entity class as abstract operation.
if (!visibility.equals(ObjectModelJavaModifier.PUBLIC)) {
addOperation(outputAbstract, opName, opType, visibility,
ObjectModelJavaModifier.ABSTRACT);
// Other operations, only in entity interface, implementations
// need to be done in implementation class created by developper
} else {
cloneOperationSignature(operation, outputInterface, true);
}
}
}
/**
* Generate properties from {@code attributes}. Generate
* constant, attribute and operations for each property.
*
* @param attributes Input attributes
* @param aClass FIXME
* @param aPackage FIXME
*/
protected void generateProperties(Collection attributes, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
for (ObjectModelAttribute attribute : attributes) {
if (!associationClass) {
// FIXME-fdesbois-2010-06-25 : Strange behavior to keep those links, will break hibernate, may be a problem in mapping
if (!attribute.isNavigable() && attribute.hasAssociationClass()) {
generatePropertyConstant(attribute);
generatePropertyAttribute(attribute, aClass, aPackage);
updateAcceptOperation(attribute, aClass, aPackage);
}
if (!attribute.isNavigable() &&
!templateHelper.hasUnidirectionalRelationOnAbstractType(
attribute.getReverseAttribute(), model)) {
continue;
}
}
// constant
generatePropertyConstant(attribute);
// attribute
generatePropertyAttribute(attribute, aClass, aPackage);
// operations
generatePropertyOperations(attribute, aClass, aPackage);
// update accept body
updateAcceptOperation(attribute, aClass, aPackage);
}
if (reverseOneToOneAttribute != null) {
ObjectModelAttribute attribute = reverseOneToOneAttribute.getReverseAttribute();
generatePropertyConstant(attribute);
generatePropertyAttribute(attribute, aClass, aPackage);
generatePropertyOperations(attribute, aClass, aPackage);
}
}
// -------------------------------------------------------------------------
// Generate for property
// -------------------------------------------------------------------------
/**
* Generate constant in interface for {@code attribute}.
*
* @param attribute Input attribute to treate
* @see #getPropertyName(ObjectModelAttribute)
*/
protected void generatePropertyConstant(ObjectModelAttribute attribute) {
String attrName = getPropertyName(attribute);
if (log.isDebugEnabled()) {
log.debug("Generate constant for property : " + attrName);
}
addAttribute(outputInterface, getConstantName(attrName), String.class,
"\"" + attrName + "\"");
}
protected void generatePropertyAttribute(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
if (outputAbstract == null) {
return;
}
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
String collectionType = getCollectionType(attribute);
if (collectionType != null) {
attrType = collectionType + "<" + attrType + ">";
}
//String attrVisibility = attr.getVisibility();
// Declaration
ObjectModelAttribute property =
addAttribute(outputAbstract, attrName, attrType, null,
//ObjectModelJavaModifier.toValue(attrVisibility),
ObjectModelJavaModifier.PROTECTED
);
// Documentation
StringBuilder buffer = new StringBuilder();
if (GeneratorUtil.hasDocumentation(attribute)) {
String attrDocumentation = attribute.getDocumentation();
buffer.append(attrDocumentation).append('\n');
}
String dbName = templateHelper.getDbName(attribute);
if (!StringUtils.isEmpty(dbName)) {
buffer.append("Nom de l'attribut en BD : ").append(dbName).append('\n');
}
setDocumentation(property, buffer.toString());
// Annotation
String annotation = new TopiaCoreTagValues().getAnnotationTagValue(attribute);
if (!StringUtils.isEmpty(annotation)) {
//FIXME Make annotation works...
//TODO tchemit 20100513 Test it still works
addAnnotation(outputAbstract, property, annotation);
}
}
/**
* Generation operations for {@code attributes}.
* One method exists for each operation to generate. Methods starting
* with 'addSingle' is for maxMultiplicity attribute = 1 and for collection
* case, methods start with 'addMultiple'. Other case are take care in each
* method (association class, reverse, entity reference, ...).
*
* @param attribute Input attribute to treate
* @param aClass Input class
* @param aPackage Input package
* @see #addSingleGetOperation(ObjectModelClass, ObjectModelAttribute, String, String)
* @see #addSingleSetOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @see #addMultipleAddOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String)
* @see #addMultipleAddAllOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String)
* @see #addMultipleSetOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String, String)
* @see #addMultipleRemoveOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @see #addMultipleClearOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String, String)
* @see #addMultipleGetOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String, Class)
* @see #addMultipleSizeOperation(ObjectModelAttribute)
* @see #addMultipleIsEmptyOperations(ObjectModelAttribute)
*/
protected void generatePropertyOperations(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
if (attribute.getMaxMultiplicity() == 1 || associationClass) {
// setXXX
addSingleSetOperation(attribute, aClass, aPackage);
boolean booleanProperty =
GeneratorUtil.isBooleanPrimitive(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (booleanProperty) {
// isXXX
addSingleGetOperation(
(ObjectModelClass) aClass,
attribute,
attrType,
JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX);
}
if (!booleanProperty || generateBooleanGetMethods) {
// getXXX
addSingleGetOperation(
(ObjectModelClass) aClass,
attribute,
attrType,
JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX);
}
} else {
// List, Set or Collection ?
Class> collectionInterfaceType = templateHelper.getCollectionType(attribute);
String collectionInterface = collectionInterfaceType.getName();
String collectionImpl = templateHelper.getCollectionInstanceType(attribute).getName();
if (!useRelativeName) {
addImport(outputInterface, collectionInterface);
addImport(outputAbstract, collectionInterface);
addImport(outputAbstract, collectionImpl);
if (!GeneratorUtil.getSimpleName(collectionInterface).equals(outputInterface.getName())
&& !GeneratorUtil.getSimpleName(collectionInterface).equals(outputAbstract.getName())
) {
collectionInterface = GeneratorUtil.getSimpleName(collectionInterface);
}
if (!GeneratorUtil.getSimpleName(collectionImpl).equals(outputInterface.getName())
&& !GeneratorUtil.getSimpleName(collectionImpl).equals(outputAbstract.getName())) {
collectionImpl = GeneratorUtil.getSimpleName(collectionImpl);
}
}
boolean ordered = JavaGeneratorUtil.isOrdered(attribute);
boolean unique = EugeneCoreTagValues.isUnique(attribute);
boolean entity = templateHelper.isEntity(attribute, model);
// addXXX
addMultipleAddOperation(attribute, aClass, aPackage, collectionImpl);
// addAllXXX
addMultipleAddAllOperation(attribute, aClass, aPackage, collectionImpl);
// setXXX
addMultipleSetOperation(attribute, aClass, aPackage, collectionInterface, collectionImpl);
// removeXXX
addMultipleRemoveOperation(attribute, aClass, aPackage);
// clearXXX
addMultipleClearOperation(attribute, aClass, aPackage, collectionInterface, collectionImpl);
// getXXX
addMultipleGetOperation(attribute, aClass, aPackage, collectionInterface, collectionInterfaceType);
if (entity) {
// getXXXTopiaIds
addMultipleGetTopiaIdsOperation(attribute, aClass, aPackage, collectionInterface, collectionImpl);
}
// sizeXXX
addMultipleSizeOperation(attribute);
// isXXXEmpty
addMultipleIsEmptyOperations(attribute);
// containsXXX
addMultipleContainsOperation(attribute, aClass, aPackage);
}
}
protected void addSingleSetOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate single 'set' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
createPropertySetterSignature(outputInterface, attrType, attrName,
"");
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
String constantName = getConstantName(attrName);
StringBuilder body = new StringBuilder();
Integer digits = topiaExtensionTagValues.getDigits(aPackage, aClass, attribute);
if (digits != null) {
addImport(outputAbstract, Numbers.class);
body.append(""
+"\n"
+" if ("+attrName+" != null) {\n"
+" // round to "+digits+" digit(s)\n"
+" "+attrName+" = Numbers.roundNDigits("+attrName+", "+digits+");\n"
+" }\n"
+" "
);
}
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" "+attrType+" oldValue = this."+attrName+";"
);
}
body.append(""
+"\n"
+" this."+attrName+" = "+attrName+";\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", oldValue, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
/**
* Add getter for simple property (neither association nor multiple).
* Will add two different operations for boolean case ('is' method and
* 'get' method). This method add the operation in both {@code
* outputAbstract} and {@code outputInterface}.
*
* @param input input class
* @param attribute ObjectModelAttribute for getter operation
* @param attrType type of the attribute
* @param operationPrefix Operation prefix : 'get' by default, if prefix
* is null
*/
protected void addSingleGetOperation(ObjectModelClass input,
ObjectModelAttribute attribute,
String attrType,
String operationPrefix) {
String attrName = getPropertyName(attribute);
if (log.isDebugEnabled()) {
log.debug("Generate single '" + operationPrefix + "' operation for property : "
+ attrName + " [" + attrType + "]");
}
String constantName = getConstantName(attrName);
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName(operationPrefix, attrName),
attrType, ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
StringBuilder body = new StringBuilder();
body.append(""
+"\n"
+" return this."+attrName+";\n"
+""
);
setOperationBody(implOperation, body.toString());
if (doDto) {
boolean isEntity = attribute.getClassifier() != null && templateHelper.isEntity(attribute.getClassifier());
for (Class> dtoType : dtoTypes) {
if (entityToDtoMapping.acceptToDtoProperty(dtoType, attrName)) {
String toDtoGetterName = entityToDtoMapping.getToDtoSimpleMethod(dtoType, attribute, operationPrefix, isEntity);
String toDtoSetterName = getJavaBeanMethodName("set", attrName);
spiToDtoOperationBody.get(dtoType).append(""+"\n"
+" dto."+toDtoSetterName+"("+toDtoGetterName+");");
if (entityToDtoMapping.acceptFromDtoProperty(dtoType, attrName, isEntity, false)) {
String fromDtoGetterName = entityToDtoMapping.getFromDtoSimpleMethod(dtoType, attribute, operationPrefix, isEntity);
if (fromDtoGetterName != null) {
String fromDtoSetterName = getJavaBeanMethodName("set", attrName);
spiFromDtoOperationBody.get(dtoType).append(""+"\n"
+" entity."+fromDtoSetterName+"("+fromDtoGetterName+");");
}
}
}
}
}
}
public String getJavaBeanMethodName(String methodPrefix, String propertyName) {
return super.getJavaBeanMethodName(methodPrefix, propertyName);
}
protected void addMultipleAddOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage, String collectionImpl) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
ObjectModelAttribute reverse = attribute.getReverseAttribute();
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'add' operation for property : " + attrName +
" [" + attrType + "]");
}
String constantName = getConstantName(attrName);
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("add", attrName),
void.class, ObjectModelJavaModifier.PACKAGE);
ObjectModelParameter param =
addParameter(interfaceOperation, attrType, attrName);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
StringBuilder body = new StringBuilder();
body.append(""
+"\n"
+" if (this."+attrName+" == null) {\n"
+" this."+attrName+" = new "+collectionImpl+"<"+attrType+">();\n"
+" }\n"
+""
);
if (reverse != null && (reverse.isNavigable() ||
templateHelper.hasUnidirectionalRelationOnAbstractType(attribute, model))) {
String getterName = getJavaBeanMethodName("get", reverse.getName());
String setterName = getJavaBeanMethodName("set", reverse.getName());
// TODO brendan 15/04/14 remove FQN
String reverseAttrType = JavaGeneratorUtil.getAttributeImplementationType(reverse, true);
if (!GeneratorUtil.isNMultiplicity(reverse)) {
body.append(""
+" "+attrName+"."+setterName+"(this);\n"
+""
);
// Don't manage reverse attribute add if attribute has associationClass
} else if (!attribute.hasAssociationClass()) {
body.append(""
+" if ("+attrName+"."+getterName+"() == null) {\n"
+" "+attrName+"."+setterName+"(new "+reverseAttrType+"());\n"
+" }\n"
+" "+attrName+"."+getterName+"().add(this);\n"
+""
);
}
}
body.append(""
+" this."+attrName+".add("+attrName+");\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", null, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleAddAllOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage, String collectionImpl) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'addAll' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("addAll", attrName),
void.class, ObjectModelJavaModifier.PACKAGE);
ObjectModelParameter param =
addParameter(interfaceOperation, "java.util.Collection<" + attrType + ">", attrName);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
String constantName = getConstantName(attrName);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
StringBuilder body = new StringBuilder();
body.append(""
+"\n"
+" if ("+attrName+" == null) {\n"
+" return;\n"
+" }\n"
+" if (this."+attrName+" == null) {\n"
+" this."+attrName+" = new "+collectionImpl+"<"+attrType+">();\n"
+" }\n"
+" this."+attrName+".addAll("+attrName+");\n"
+""
);
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", null, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleSetOperation(ObjectModelAttribute attribute,
ObjectModelClassifier aClass, ObjectModelPackage aPackage,
String collectionInterface,
String collectionImpl) {
String attrName = getPropertyName(attribute);
String referenceType = getPropertyType(attribute, aClass, aPackage);
String attrType = collectionInterface + "<" + referenceType + ">";
String constantName = getConstantName(attrName);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'set' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
createPropertySetterSignature(outputInterface, attrType, attrName,
"");
if (outputAbstract == null) {
return;
}
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
referenceType = GeneratorUtil.getSimpleName(referenceType);
}
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" // Copy elements to keep data for fire with new reference\n"
+" "+attrType+" oldValue = this."+attrName+" != null ? new "+collectionImpl+"<"+referenceType+">(this."+attrName+") : null;"
);
}
body.append(""
+"\n"
+" this."+attrName+" = "+attrName+";\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", oldValue, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleRemoveOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
ObjectModelAttribute reverse = attribute.getReverseAttribute();
String constantName = getConstantName(attrName);
if (log.isDebugEnabled()) {
log.debug("Generate 'remove' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("remove", attrName),
void.class, ObjectModelJavaModifier.PACKAGE);
ObjectModelParameter param =
addParameter(interfaceOperation, attrType, attrName);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
StringBuilder body = new StringBuilder();
body.append(""
+"\n"
+" if (this."+attrName+" == null || !this."+attrName+".remove("+attrName+")) {\n"
+" throw new IllegalArgumentException(\"List does not contain given element\");\n"
+" }\n"
+" "
);
if (reverse != null && (reverse.isNavigable() ||
templateHelper.hasUnidirectionalRelationOnAbstractType(attribute, model))) {
String getterName = getJavaBeanMethodName("get", reverse.getName());
String setterName = getJavaBeanMethodName("set", reverse.getName());
if (!GeneratorUtil.isNMultiplicity(reverse)) {
body.append(""
+" "+attrName+"."+setterName+"(null);\n"
+" "
);
// Don't manage reverse attribute remove if attribute has associationClass
} else if (!attribute.hasAssociationClass()) {
body.append(""
+" "+attrName+"."+getterName+"().remove(this);\n"
+" "
);
}
}
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", null, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleClearOperation(ObjectModelAttribute attribute,
ObjectModelClassifier aClass, ObjectModelPackage aPackage,
String collectionInterface,
String collectionImpl) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
ObjectModelAttribute reverse = attribute.getReverseAttribute();
String constantName = getConstantName(attrName);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'clear' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("clear", attrName),
void.class, ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
if (!useRelativeName) {
attrType = GeneratorUtil.getSimpleName(attrType);
}
StringBuilder body = new StringBuilder(""
+"\n"
+" if (this."+attrName+" == null) {\n"
+" return;\n"
+" }\n"
+""
);
if (reverse != null && (reverse.isNavigable() ||
templateHelper.hasUnidirectionalRelationOnAbstractType(attribute, model))) {
String getterName = getJavaBeanMethodName("get", reverse.getName());
String setterName = getJavaBeanMethodName("set", reverse.getName());
body.append(""
+" for ("+attrType+" item : this."+attrName+") {\n"
+""
);
if (!GeneratorUtil.isNMultiplicity(reverse)) {
body.append(""
+" item."+setterName+"(null);\n"
+""
);
// Don't manage reverse attribute remove if attribute has associationClass
} else if (!attribute.hasAssociationClass()) {
body.append(""
+" item."+getterName+"().remove(this);\n"
+""
);
}
body.append(""
+" }\n"
+""
);
}
if (generatePropertyChangeSupport) {
body.append(""
+" "+collectionInterface+"<"+attrType+"> oldValue = new "+collectionImpl+"<>(this."+attrName+");\n"
+""
);
}
body.append(""
+" this."+attrName+".clear();\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" firePropertyChange("+constantName+", oldValue, this."+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleGetOperation(ObjectModelAttribute attribute,
ObjectModelClassifier aClass, ObjectModelPackage aPackage,
String collectionInterface, Class> collectionInterfaceType) {
String attrName = getPropertyName(attribute);
String attrType = collectionInterface + "<" + getPropertyType(attribute, aClass, aPackage) + ">";
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'get' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("get", attrName),
attrType, ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
setOperationBody(implOperation, ""
+"\n"
+" return "+attrName+";\n"
+" "
);
if (doDto) {
boolean isEntity = attribute.getClassifier() != null && templateHelper.isEntity(attribute.getClassifier());
for (Class> dtoType : dtoTypes) {
if (entityToDtoMapping.acceptToDtoProperty(dtoType, attrName)) {
String toDtoGetterName = entityToDtoMapping.getToDtoMultipleMethod(dtoType, attribute, isEntity);
String toDtoSetterName = getJavaBeanMethodName("set", attrName);
spiToDtoOperationBody.get(dtoType).append(""+"\n"
+" dto."+toDtoSetterName+"("+toDtoGetterName+");"
);
if (entityToDtoMapping.acceptFromDtoProperty(dtoType, attrName, isEntity, true)) {
String fromDtoGetterName = entityToDtoMapping.getFromDtoMultipleMethod(dtoType, attribute, collectionInterfaceType, isEntity);
if (fromDtoGetterName != null) {
String fromDtoSetterName = getJavaBeanMethodName("set", attrName);
spiFromDtoOperationBody.get(dtoType).append(""+"\n"
+" entity."+fromDtoSetterName+"("+fromDtoGetterName+");"
);
}
}
}
if (entityToDtoMapping.acceptToDtoProperty(dtoType, attrName + "Size")) {
String toDtoSetterName = getJavaBeanMethodName("set", attrName + "Size");
String toDtoGetterName = getJavaBeanMethodName("get", attrName + "Size");
spiToDtoOperationBody.get(dtoType).append(""+"\n"
+" dto."+toDtoSetterName+"(entity."+toDtoGetterName+"());"
);
}
if (entityToDtoMapping.acceptToDtoProperty(dtoType, attrName + "Empty")) {
String toDtoSetterName = getJavaBeanMethodName("set", attrName + "Empty");
String toDtoGetterName = getJavaBeanMethodName("is", attrName + "Empty");
spiToDtoOperationBody.get(dtoType).append(""+"\n"
+" dto."+toDtoSetterName+"(entity."+toDtoGetterName+"());"
);
}
}
}
}
protected void addMultipleGetTopiaIdsOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage, String collectionInterface, String collectionImpl) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
String getterName = getJavaBeanMethodName("get", attrName);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'getTopiaIds' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("get", attrName) + "TopiaIds",
collectionInterface + "", ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
addImport(outputAbstract, TopiaEntity.class);
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
setOperationBody(implOperation, ""
+"\n"
+" "+collectionInterface+" topiaIds = new "+collectionImpl+"();\n"
+" "+collectionInterface+"<"+attrType+"> tmp = "+getterName+"();\n"
+" if (tmp != null) {\n"
+" for (TopiaEntity topiaEntity : tmp) {\n"
+" topiaIds.add(topiaEntity.getTopiaId());\n"
+" }\n"
+" }\n"
+" return topiaIds;\n"
+" "
);
}
protected void addMultipleSizeOperation(ObjectModelAttribute attribute) {
String attrName = getPropertyName(attribute);
log.debug(String.format("Generate multiple '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);
setOperationBody(implOperation, ""+"\n"
+" if ("+attrName+" == null) {\n"
+" return 0;\n"
+" }\n"
+" return "+attrName+".size();\n"
+" "
);
}
protected void addMultipleIsEmptyOperations(ObjectModelAttribute attribute) {
String attrName = getPropertyName(attribute);
log.debug(String.format("Generate multiple 'isEmpty' operation for property : %s", attrName));
String sizeMethodName = getJavaBeanMethodName("get", attrName + "Size");
// isEmpty Interface operation
String isEmptyMethodName = getJavaBeanMethodName("is", attrName) + "Empty";
ObjectModelOperation isEmptyInterfaceOperation =
addOperation(outputInterface, isEmptyMethodName,
boolean.class, ObjectModelJavaModifier.PACKAGE);
// isNotEmpty Interface operation
ObjectModelOperation isNotEmptyInterfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("is", attrName) + "NotEmpty",
boolean.class, ObjectModelJavaModifier.PACKAGE);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation isEmptyOperationImpl = createImplOperation(isEmptyInterfaceOperation);
setOperationBody(isEmptyOperationImpl, ""+"\n"
+" int size = "+sizeMethodName+"();\n"
+" return size == 0;\n"
+" "
);
// Implementation
ObjectModelOperation isNotEmptyOperationImpl = createImplOperation(isNotEmptyInterfaceOperation);
setOperationBody(isNotEmptyOperationImpl, ""+"\n"
+" boolean empty = "+isEmptyMethodName+"();\n"
+" return !empty;\n"
+" "
);
}
protected void addMultipleContainsOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'contains' operation for property : " + attrName);
}
String methodName = getJavaBeanMethodName("contains", attrName);
ObjectModelOperation isEmptyInterfaceOperation =
addOperation(outputInterface, methodName,
boolean.class, ObjectModelJavaModifier.PACKAGE);
addParameter(isEmptyInterfaceOperation, attrType, attrName);
if (outputAbstract == null) {
return;
}
// Implementation
ObjectModelOperation isEmptyOperationImpl = createImplOperation(isEmptyInterfaceOperation);
setOperationBody(isEmptyOperationImpl, ""
+"\n"
+" boolean contains = this."+attrName+" !=null && this."+attrName+".contains("+attrName+");\n"
+" return contains;\n"
+" "
);
}
// -------------------------------------------------------------------------
// Generate util operations
// -------------------------------------------------------------------------
protected void createAcceptOperation() {
if (outputAbstract == null) {
return;
}
ObjectModelOperation acceptOperation = addOperation(outputAbstract, "accept", void.class);
addAnnotation(outputAbstract, acceptOperation, Override.class);
addParameter(acceptOperation, TopiaEntityVisitor.class, "visitor");
addException(acceptOperation, TopiaException.class);
setOperationBody(acceptOperation, ""
+"\n"
+" visitor.start(this);\n"
+" accept0(visitor);\n"
+" visitor.end(this);\n"
+" "
);
}
protected void createAcceptInternalOperation(ObjectModelClass input) {
if (outputAbstract == null) {
return;
}
boolean withSuperEntity = false;
for (ObjectModelClassifier parent : input.getSuperclasses()) {
if (templateHelper.isEntity(parent)) {
withSuperEntity = true;
break;
}
}
if (doDto) {
Class> dtoTypeContract = entityToDtoMapping.getDtoContract(input);
dtoTypes = entityToDtoMapping.getDtoTypes(input);
spiToDtoOperationBody = new LinkedHashMap<>();
spiFromDtoOperationBody = new LinkedHashMap<>();
addImport(outputAbstract, dtoTypeContract);
for (Class> dtoType : dtoTypes) {
String dtoTypeName = dtoType.getName();
spiToDtoOperationBody.put(dtoType, new StringBuilder(""));
spiFromDtoOperationBody.put(dtoType, new StringBuilder(""));
}
}
internalAcceptOperation = addOperation(outputAbstract, "accept0", void.class, ObjectModelJavaModifier.PROTECTED);
addParameter(internalAcceptOperation, TopiaEntityVisitor.class, "visitor");
addException(internalAcceptOperation, TopiaException.class);
if (withSuperEntity) {
addAnnotation(outputAbstract, internalAcceptOperation, Override.class);
internalAcceptOperationBody = new StringBuilder(""
+"\n"
+" super.accept0(visitor);\n"
+""
);
} else {
internalAcceptOperationBody = new StringBuilder(""
+"\n"
+""
);
}
}
protected void updateAcceptOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
if (outputAbstract == null) {
return;
}
String attrName = GeneratorUtil.getSimpleName(getPropertyName(attribute));
String attrType = importAndSimplify(outputAbstract, getPropertyType(attribute, aClass, aPackage));
// remove custom generics http://nuiton.org/issues/3453
attrType = GeneratorUtil.removeAnyGenericDefinition(attrType);
String collectionType = getCollectionType(attribute);
String constantName = getConstantName(attrName);
if (collectionType != null) {
internalAcceptOperationBody.append(""
+" visitor.visit(this, "+constantName+", "+collectionType+".class, "+attrType+".class, "+attrName+");\n"
+""
);
} else {
internalAcceptOperationBody.append(""
+" visitor.visit(this, "+constantName+", "+attrType+".class, "+attrName+");\n"
+""
);
}
}
protected void closeAcceptInternalOperation() {
if (outputAbstract == null) {
return;
}
setOperationBody(internalAcceptOperation, internalAcceptOperationBody.toString() + ""
+" "
);
}
protected String generateToDtoOperation(Class> dtoType) {
String content = spiToDtoOperationBody.get(dtoType).toString().trim();
return ""+"\n"
+" super.toDto(referentialLocale, entity, dto);\n"
+" "+content+"\n"
+" dto.postInit();";
}
protected String generateFromDtoOperation(Class> dtoType) {
String content = spiFromDtoOperationBody.get(dtoType).toString().trim();
return ""+"\n"
+" super.fromDto(referentialLocale, entity, dto);\n"
+" "+content+"";
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
protected boolean isAbstract(ObjectModelClass clazz) {
if (clazz.isAbstract()) {
return true;
}
//Une classe peut être abstraite si elle a des méthodes définies dans
// ses superinterface et non implantées dans ses superclasses
Collection allInterfaceOperations =
clazz.getAllInterfaceOperations(true);
allInterfaceOperations.removeAll(clazz.getAllOtherOperations(true));
for (ObjectModelOperation op : allInterfaceOperations) {
boolean implementationFound = false;
for (ObjectModelClass superClazz : clazz.getSuperclasses()) {
for (ObjectModelOperation matchingOp :
superClazz.getOperations(op.getName())) {
implementationFound = op.equals(matchingOp) &&
!matchingOp.isAbstract();
if (implementationFound) {
break;
}
}
if (implementationFound) {
break;
}
}
if (!implementationFound) {
if (log.isDebugEnabled()) {
log.debug(clazz.getName() + " : abstract operation " + op);
}
return true;
}
}
return false;
}
protected String getCollectionType(ObjectModelAttribute attribute) {
String result = null;
if (!associationClass && GeneratorUtil.isNMultiplicity(attribute)) {
result = templateHelper.getCollectionType(attribute).getName();
}
return result;
}
protected String getPropertyName(ObjectModelAttribute attribute) {
String propertyName = attribute.getName();
if (!associationClass && attribute.hasAssociationClass()) {
propertyName = GeneratorUtil.getAssocAttrName(attribute);
}
return propertyName;
}
protected String getPropertyType(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String propertyType = topiaHibernateTagValues.getAttributeType(attribute, aClass, aPackage, model);
if (propertyType == null) {
propertyType = attribute.getType();
}
if (!associationClass && attribute.hasAssociationClass()) {
propertyType = attribute.getAssociationClass().getQualifiedName();
}
return propertyType;
}
protected ObjectModelOperation createImplOperation(ObjectModelOperation interfaceOperation) {
ObjectModelOperation implOperation =
cloneOperationSignature(interfaceOperation, outputAbstract, false);
addAnnotation(outputAbstract, implOperation, Override.class);
return implOperation;
}
/**
* TODO-fdesbois-2010-06-25 : This method can be put in JavaBuilder or ObjectModelTransformerToJava
*
* This method create an set operation in {@code classifier} with
* {@code propertyType} as return type and {@code propertyName} used for
* operation name ('set[propertyName]'). {@code operationDocument} can
* also be added to the operation created. Only signature with default
* visibility will be added.
*
* @param classifier Classifier where the operation will be added
* @param propertyType Type of the property (better if qualified name)
* @param propertyName Name of the property to set
* @param operationDocumentation Documentation for the operation
* @return the created operation
*/
protected ObjectModelOperation createPropertySetterSignature(ObjectModelClassifier classifier,
String propertyType,
String propertyName,
String operationDocumentation) {
// Operation
ObjectModelOperation operation =
addOperation(classifier,
getJavaBeanMethodName("set", propertyName), void.class);
ObjectModelParameter param =
addParameter(operation, propertyType, propertyName);
// Documentation
if (StringUtils.isNotEmpty(operationDocumentation)) {
setDocumentation(operation, operationDocumentation);
setDocumentation(param, "La valeur de l'attribut à positionner.");
}
return operation;
}
protected void addInterface(List interfaceAlreadyDone,
ObjectModelClassifier output,
ObjectModelClassifier interfaze) {
String qualifiedName = interfaze.getQualifiedName();
if (!interfaceAlreadyDone.contains(qualifiedName)) {
interfaceAlreadyDone.add(qualifiedName);
if (output != null) {
// add it to output
addInterface(output, qualifiedName);
if (log.isTraceEnabled()) {
log.trace("Add interface " + qualifiedName + " on " +
output.getQualifiedName());
}
} else {
if (log.isTraceEnabled()) {
log.trace("Skip included interface " + qualifiedName);
}
}
// scan also all interfaces or super-classes of it
for (ObjectModelClassifier parent : interfaze.getInterfaces()) {
addInterface(interfaceAlreadyDone, null, parent);
}
}
}
protected void addInterface(List interfaceAlreadyDone,
ObjectModelClassifier output,
Class> clazz) {
String qualifiedName = clazz.getName();
if (!interfaceAlreadyDone.contains(qualifiedName)) {
// add it to output
addInterface(output, qualifiedName);
}
}
protected void generateSimpleClassMapping(String className, boolean useSimpleName, Class> superClass, String sourceType, String targetType, Class> builderType, String buildMethod, Map mapping) {
ObjectModelClass output = createClass(className, getDefaultPackageName());
addImport(output, ImmutableClassMapping.class);
String initMethod = builderType.getName();
if (useSimpleName) {
addImport(output, builderType);
addImport(output, sourceType);
addImport(output, targetType);
sourceType = GeneratorUtil.getSimpleName(sourceType);
targetType = GeneratorUtil.getSimpleName(targetType);
initMethod = GeneratorUtil.getSimpleName(initMethod);
}
setSuperClass(output, superClass);
StringBuilder body = new StringBuilder(""+"\n"
+" super("
);
body.append(""+""+initMethod+".<"+sourceType+", "+targetType+">builder()"
);
mapping.forEach((source, target) -> body.append(""+"\n"
+" .put("+source+".class, "+target+")"
));
body.append(""+"\n"
+" ."+buildMethod+"());\n"
+" "
);
ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC);
setOperationBody(constructor, body.toString());
}
protected void addContractTypeMethod(ObjectModelClass input, ObjectModelClassifier output) {
ObjectModelJavaModifier[] modifier = output instanceof ObjectModelInterface ? new ObjectModelJavaModifier[]{ObjectModelJavaModifier.DEFAULT} : new ObjectModelJavaModifier[]{ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.FINAL};
String type = output instanceof ObjectModelInterface ? input.getName() : output.getName();
ObjectModelOperation contractType = addOperation(output,
"contractType",
String.format("Class<%s>", type),
modifier);
addAnnotation(output, contractType, Override.class);
setOperationBody(contractType, ""+"\n"
+" return "+type+".class;\n"
+" ");
}
}