org.nuiton.topia.templates.EntityTransformer Maven / Gradle / Ivy
The newest version!
package org.nuiton.topia.templates;
/*
* #%L
* ToPIA :: Templates
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2004 - 2014 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.extension.tagvalue.TagValueUtil;
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.TopiaDao;
import org.nuiton.topia.persistence.TopiaDaoSupplier;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityContextable;
import org.nuiton.topia.persistence.TopiaEntityVisitor;
import org.nuiton.topia.persistence.TopiaException;
import org.nuiton.topia.persistence.event.ListenableTopiaEntity;
import org.nuiton.topia.persistence.internal.AbstractTopiaEntity;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
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
*/
@Component( role = Template.class, hint="org.nuiton.topia.templates.EntityTransformer")
public class EntityTransformer extends ObjectModelTransformerToJava {
/** Logger */
private static final Log log = LogFactory.getLog(EntityTransformer.class);
protected ObjectModelInterface outputInterface;
protected ObjectModelClass outputAbstract;
protected ObjectModelClass outputImpl;
private boolean associationClass;
protected boolean generateInterface;
protected boolean generateAbstract;
protected boolean generateImpl;
protected boolean generateBooleanGetMethods;
protected boolean generatePropertyChangeSupport;
protected TopiaTemplateHelper templateHelper;
protected final TopiaCoreTagValues topiaCoreTagValues;
protected final TopiaHibernateTagValues topiaHibernateTagValues;
public EntityTransformer() {
this.topiaCoreTagValues = new TopiaCoreTagValues();
this.topiaHibernateTagValues = new TopiaHibernateTagValues();
}
protected void clean() {
outputInterface = null;
outputAbstract = null;
outputImpl = null;
}
@Override
public void transformFromClass(ObjectModelClass input) {
if (templateHelper == null) {
templateHelper = new TopiaTemplateHelper(model);
}
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());
}
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);
// Implement toString operation
if (!topiaCoreTagValues.getNotGenerateToStringTagValue(input, aPackage, model)) {
generateToStringOperation(input);
}
// Generate serialVersionUID on abstract class
generateSerialVersionUID(input, outputAbstract);
// Generate Entity Implementation class
if (generateImpl) {
generateImpl(input);
generateSerialVersionUID(input, outputImpl);
}
// Clean data output after transformation
clean();
}
protected void generateSerialVersionUID(ObjectModelClass input,
ObjectModelClass ouput) {
// serialVersionUID
String svUID = TagValueUtil.findTagValue(TopiaCoreTagValues.Store.serialVersionUID, input);
if (svUID == null) {
// use a default one
svUID = GeneratorUtil.generateSerialVersionUID(ouput) + "L";
}
addConstant(ouput, GeneratorUtil.SERIAL_VERSION_UID, long.class, svUID,
ObjectModelJavaModifier.PRIVATE);
}
protected void createEntityInterface(ObjectModelPackage aPackage,
ObjectModelClass input) {
outputInterface = createInterface(input.getName(),
input.getPackageName());
// Documentation
if (GeneratorUtil.hasDocumentation(input)) {
setDocumentation(outputInterface, input.getDocumentation());
}
if (log.isTraceEnabled()) {
log.trace("Will add interfaces on " +
outputInterface.getQualifiedName());
}
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) {
Class> interfaze = TopiaEntity.class;
if (topiaCoreTagValues.getContextableTagValue(input, aPackage, model)) {
interfaze = TopiaEntityContextable.class;
}
addInterface(interfaceAlreadyDone,
outputInterface,
interfaze);
} else if (topiaCoreTagValues.getContextableTagValue(input, aPackage, model)) {
// Even if there is no need to implement TopiaEntity, it might be
// necessary to implement TopiaEntityContextable
addInterface(interfaceAlreadyDone,
outputInterface,
TopiaEntityContextable.class);
}
if (generatePropertyChangeSupport) {
addInterface(interfaceAlreadyDone,
outputInterface,
ListenableTopiaEntity.class);
}
}
protected void createEntityAbstractClass(ObjectModelPackage aPackage,
ObjectModelClass input) {
outputAbstract = createAbstractClass(input.getName() + "Abstract",
input.getPackageName());
// 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 alwyas use an Impl, moreover use the util method instead
String extendClass = templateHelper.getDOType(parent, model);
// String extendClass = parent.getQualifiedName();
// //Si une des classes parentes définies des méthodes abstraites, son
// // impl ne sera pas créé
// boolean abstractParent = templateHelper.shouldBeAbstract(parent);
// if (templateHelper.isEntity(parent)) {
// if (abstractParent) {
// extendClass += "Abstract";
// } else {
// extendClass += "Impl";
// }
// }
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);
}
if (topiaCoreTagValues.getContextableTagValue(input, aPackage, model)) {
addContextableMethods(input, outputAbstract);
}
}
/**
* Ajout les methodes necessaire à l'interface {@link TopiaEntityContextable}
* si le tagValue {@link TopiaCoreTagValues.Store#contextable} est renseigné.
*
* @param input FIXME
* @param outputAbstract FIXME
*/
protected void addContextableMethods(ObjectModelClass input,
ObjectModelClass outputAbstract) {
addImport(outputAbstract, TopiaDaoSupplier.class);
addImport(outputAbstract, TopiaDao.class);
// topiaContext attribute
ObjectModelAttribute topiaContextAttribute = addAttribute(
outputAbstract, "topiaDaoSupplier", TopiaDaoSupplier.class, null,
ObjectModelJavaModifier.PROTECTED, ObjectModelJavaModifier.TRANSIENT);
setDocumentation(topiaContextAttribute,
"TopiaDAO instance associated with the current \n" +
"instance. For internal usage only");
ObjectModelOperation op;
op = addOperation(outputAbstract,
"getTopiaDaoSupplier", TopiaDaoSupplier.class,
ObjectModelJavaModifier.PUBLIC);
setDocumentation(op, "@since 3.0");
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" return topiaDaoSupplier;\n"
+" "
);
op = addOperation(outputAbstract,
"setTopiaDaoSupplier", "void",
ObjectModelJavaModifier.PUBLIC);
addException(op, TopiaException.class);
addParameter(op, TopiaDaoSupplier.class, "topiaDaoSupplier");
setDocumentation(op, "@since 3.0");
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" if (this.topiaDaoSupplier == null) {\n"
+" this.topiaDaoSupplier = topiaDaoSupplier;\n"
+" }\n"
+" "
);
String daoClassName = templateHelper.getConcreteDaoName(input);
op = addOperation(outputAbstract,
"getInternalDao", daoClassName,
ObjectModelJavaModifier.PROTECTED);
setDocumentation(op, "@since 3.0");
setOperationBody(op, ""
+"\n"
+" TopiaDaoSupplier daoSupplier = getTopiaDaoSupplier();\n"
+" "+daoClassName+" result = null;\n"
+" if (daoSupplier != null) { // This may happend when entity is created manually\n"
+" result = daoSupplier.getDao("+input.getName()+".class, "+daoClassName+".class);\n"
+" }\n"
+" return result;\n"
+" "
);
op = addOperation(outputAbstract, "getGenericEntityDao", "TopiaDao>",
ObjectModelJavaModifier.PUBLIC);
addAnnotation(outputAbstract, op, Override.class);
setDocumentation(op, "@since 3.0");
setOperationBody(op, ""
+"\n"
+" return getInternalDao();\n"
+" "
);
op = addOperation(outputAbstract, "update", "void",
ObjectModelJavaModifier.PUBLIC);
addException(op, TopiaException.class);
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" getInternalDao().update(this);\n"
+" "
);
op = addOperation(outputAbstract, "delete", "void", ObjectModelJavaModifier.PUBLIC);
addException(op, TopiaException.class);
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" getInternalDao().delete(this);\n"
+" "
);
op = addOperation(outputAbstract, "getComposite",
List.class.getName() + '<' + TopiaEntity.class.getName() + '>',
ObjectModelJavaModifier.PUBLIC);
addException(op, TopiaException.class);
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" List result = getInternalDao().getComposite(this);\n"
+" return result;\n"
+" "
);
op = addOperation(outputAbstract, "getAggregate",
List.class.getName() + '<' + TopiaEntity.class.getName() + '>',
ObjectModelJavaModifier.PUBLIC);
addException(op, TopiaException.class);
addAnnotation(outputAbstract, op, Override.class);
setOperationBody(op, ""
+"\n"
+" List result = getInternalDao().getAggregate(this);\n"
+" return result;\n"
+" "
);
}
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);
}
}
// -------------------------------------------------------------------------
// 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) {
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(ObjectModelAttribute, String, String)
* @see #addSingleSetOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @see #addMultipleAddOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage, String)
* @see #addMultipleAddAllOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @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)
* @see #addMultipleGetByTopiaIdOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @see #addMultipleGetOperationFromEntity(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
* @see #addMultipleSizeOperation(ObjectModelAttribute)
* @see #addMultipleIsEmptyOperations(ObjectModelAttribute)
* @see #addMultipleGetByIndexOperation(ObjectModelAttribute, ObjectModelClassifier, ObjectModelPackage)
*/
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(
attribute,
attrType,
JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX);
}
if (!booleanProperty || generateBooleanGetMethods) {
// getXXX
addSingleGetOperation(
attribute,
attrType,
JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX);
}
} else {
// List, Set or Collection ?
String collectionInterface = templateHelper.getCollectionType(attribute).getName();
String collectionImpl = templateHelper.getCollectionInstanceType(attribute).getName();
addImport(outputInterface, collectionInterface);
addImport(outputAbstract, collectionInterface);
addImport(outputAbstract, collectionImpl);
collectionInterface =
GeneratorUtil.getSimpleName(collectionInterface);
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);
if (ordered && !unique) {
// addXXX(index)
addMultipleAddAtIndexOperation(attribute, aClass, aPackage, collectionImpl);
}
// addAllXXX
addMultipleAddAllOperation(attribute, aClass, aPackage);
// setXXX
addMultipleSetOperation(attribute, aClass, aPackage, collectionInterface, collectionImpl);
// removeXXX
addMultipleRemoveOperation(attribute, aClass, aPackage);
if (ordered && !unique) {
// removeXXX(index)
addMultipleRemoveAtIndexOperation(attribute, aClass, aPackage);
}
// clearXXX
addMultipleClearOperation(attribute, aClass, aPackage, collectionInterface, collectionImpl);
// getXXX
addMultipleGetOperation(attribute, aClass, aPackage, collectionInterface);
if (ordered) {
// getXXX(index)
addMultipleGetByIndexOperation(attribute, aClass, aPackage);
}
if (entity) {
// getXXXByTopiaId
addMultipleGetByTopiaIdOperation(attribute, aClass, aPackage);
// 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,
"");
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
String constantName = getConstantName(attrName);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" "+attrType+" oldValue = this."+attrName+";\n"
+" fireOnPreWrite("+constantName+", oldValue, "+attrName+");"
);
}
body.append(""
+"\n"
+" this."+attrName+" = "+attrName+";\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" fireOnPostWrite("+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 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(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);
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" fireOnPreRead("+constantName+", "+attrName+");"
);
}
body.append(""
+"\n"
+" "+attrType+" result = this."+attrName+";\n"
+""
);
if (generatePropertyChangeSupport) {
body.append(""
+" fireOnPostRead("+constantName+", "+attrName+");\n"
+""
);
}
body.append(""
+" return result;\n"
+" "
);
setOperationBody(implOperation, body.toString());
}
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);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" fireOnPreWrite("+constantName+", null, "+attrName+");"
);
}
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(""
+" fireOnPostWrite("+constantName+", this."+attrName+".size(), null, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleAddAtIndexOperation(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);
addParameter(interfaceOperation, int.class, "index");
ObjectModelParameter param =
addParameter(interfaceOperation, attrType, attrName);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" fireOnPreWrite("+constantName+", null, "+attrName+");"
);
}
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(index, this);\n"
+""
);
}
}
body.append(""
+" this."+attrName+".add(index, "+attrName+");\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" fireOnPostWrite("+constantName+", index, null, "+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleAddAllOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
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, "Iterable<" + attrType + ">", attrName);
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
String addMethodName = getJavaBeanMethodName("add", attrName);
setOperationBody(implOperation, ""
+"\n"
+" if ("+attrName+" == null) {\n"
+" return;\n"
+" }\n"
+" for ("+attrType+" item : "+attrName+") {\n"
+" "+addMethodName+"(item);\n"
+" }\n"
+" "
);
}
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,
"");
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
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;\n"
+" fireOnPreWrite("+constantName+", oldValue, "+attrName+");"
);
}
body.append(""
+"\n"
+" this."+attrName+" = "+attrName+";\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" fireOnPostWrite("+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);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" fireOnPreWrite("+constantName+", "+attrName+", null);"
);
}
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(""
+" fireOnPostWrite("+constantName+", this."+attrName+".size() + 1, "+attrName+", null);\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleRemoveAtIndexOperation(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);
addParameter(interfaceOperation, int.class, "index");
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
StringBuilder body = new StringBuilder();
if (generatePropertyChangeSupport) {
body.append(""
+"\n"
+" fireOnPreWrite("+constantName+", "+attrName+", null);"
);
}
body.append(""
+"\n"
+" if (this."+attrName+" == null) {\n"
+" throw new IllegalArgumentException(\"List does not contain given element\");\n"
+" }\n"
+" "+attrType+" oldValue = this."+attrName+".remove(index);\n"
+" if (oldValue == null) {\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(""
+" oldValue."+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(""
+" fireOnPostWrite("+constantName+", index, oldValue, null);\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);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
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+"<"+attrType+">(this."+attrName+");\n"
+" fireOnPreWrite("+constantName+", oldValue, this."+attrName+");\n"
+""
);
}
body.append(""
+" this."+attrName+".clear();\n"
+" "
);
if (generatePropertyChangeSupport) {
body.append(""
+" fireOnPostWrite("+constantName+", oldValue, this."+attrName+");\n"
+" "
);
}
setOperationBody(implOperation, body.toString());
}
protected void addMultipleGetOperation(ObjectModelAttribute attribute,
ObjectModelClassifier aClass, ObjectModelPackage aPackage,
String collectionInterface) {
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);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
setOperationBody(implOperation, ""
+"\n"
+" return "+attrName+";\n"
+" "
);
}
protected void addMultipleGetByIndexOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'getByTopiaId' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("get", attrName),
attrType, ObjectModelJavaModifier.PACKAGE);
ObjectModelParameter param =
addParameter(interfaceOperation, int.class, "index");
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
addImport(outputAbstract, TopiaEntityHelper.class);
setOperationBody(implOperation, ""
+"\n"
+" return TopiaEntityHelper.getEntityByIndex("+attrName+", index);\n"
+" "
);
}
protected void addMultipleGetByTopiaIdOperation(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'getByTopiaId' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("get", attrName) + "ByTopiaId",
attrType, ObjectModelJavaModifier.PACKAGE);
ObjectModelParameter param =
addParameter(interfaceOperation, String.class, "topiaId");
// Implementation
ObjectModelOperation implOperation =
createImplOperation(interfaceOperation);
addImport(outputAbstract, TopiaEntityHelper.class);
setOperationBody(implOperation, ""
+"\n"
+" return TopiaEntityHelper.getEntityByTopiaId("+attrName+", topiaId);\n"
+" "
);
}
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);
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 addMultipleGetOperationFromEntity(ObjectModelAttribute attribute, ObjectModelClassifier aClass, ObjectModelPackage aPackage) {
// reference to the real attribute name
String referenceName = attribute.getName();
String referenceType = attribute.getType();
String referenceGetterName = getJavaBeanMethodName("get", referenceName);
// association attribute name
String attrName = getPropertyName(attribute);
String attrType = getPropertyType(attribute, aClass, aPackage);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'getFromEntity' operation for property : " + attrName +
" [" + attrType + "]");
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface,
getJavaBeanMethodName("get", attrName), attrType);
addParameter(interfaceOperation, referenceType, referenceName);
// Implementation
ObjectModelOperation implOperation = createImplOperation(interfaceOperation);
attrType = GeneratorUtil.getSimpleName(attrType);
setOperationBody(implOperation, ""
+"\n"
+" if ("+referenceName+" == null || this."+attrName+" == null) {\n"
+" return null;\n"
+" }\n"
+" for ("+attrType+" item : this."+attrName+") {\n"
+" if ("+referenceName+".equals(item."+referenceGetterName+"())) {\n"
+" return item;\n"
+" }\n"
+" }\n"
+" return null;\n"
+" "
);
}
protected void addMultipleSizeOperation(ObjectModelAttribute attribute) {
String attrName = getPropertyName(attribute);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'size' operation for property : " + attrName);
}
// Interface operation
ObjectModelOperation interfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("size", attrName),
int.class, ObjectModelJavaModifier.PACKAGE);
// 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);
if (log.isDebugEnabled()) {
log.debug("Generate multiple 'isEmpty' operation for property : " + attrName);
}
String sizeMethodName = getJavaBeanMethodName("size", attrName);
// isEmpty Interface operation
String isEmptyMethodName = getJavaBeanMethodName("is", attrName) + "Empty";
ObjectModelOperation isEmptyInterfaceOperation =
addOperation(outputInterface, isEmptyMethodName,
boolean.class, ObjectModelJavaModifier.PACKAGE);
// Implementation
ObjectModelOperation isEmptyOperationImpl = createImplOperation(isEmptyInterfaceOperation);
setOperationBody(isEmptyOperationImpl, ""
+"\n"
+" int size = "+sizeMethodName+"();\n"
+" return size == 0;\n"
+" "
);
// isNotEmpty Interface operation
ObjectModelOperation isNotEmptyInterfaceOperation =
addOperation(outputInterface, getJavaBeanMethodName("is", attrName) + "NotEmpty",
boolean.class, ObjectModelJavaModifier.PACKAGE);
// 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);
// Implementation
ObjectModelOperation isEmptyOperationImpl = createImplOperation(isEmptyInterfaceOperation);
setOperationBody(isEmptyOperationImpl, ""
+"\n"
+" boolean contains = this."+attrName+" !=null && this."+attrName+".contains("+attrName+");\n"
+" return contains;\n"
+" "
);
}
// -------------------------------------------------------------------------
// Generate util operations
// -------------------------------------------------------------------------
private ObjectModelOperation internalAcceptOperation;
private StringBuilder internalAcceptOperationBody;
protected void createAcceptOperation() {
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) {
boolean withSuperEntity = false;
for (ObjectModelClassifier parent : input.getSuperclasses()) {
if (templateHelper.isEntity(parent)) {
withSuperEntity = true;
break;
}
}
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) {
String attrName =
GeneratorUtil.getSimpleName(getPropertyName(attribute));
String attrType =
GeneratorUtil.getSimpleName(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) {
collectionType = GeneratorUtil.getSimpleName(collectionType);
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() {
setOperationBody(internalAcceptOperation, internalAcceptOperationBody.toString() + ""
+" "
);
}
protected void generateToStringOperation(ObjectModelClass input) {
if (log.isDebugEnabled()) {
log.debug("generate toString method for entity " +
outputInterface.getQualifiedName());
}
ObjectModelOperation operation =
addOperation(outputAbstract, "toString", String.class);
addAnnotation(outputAbstract, operation, Override.class);
addImport(outputAbstract, ToStringBuilder.class);
StringBuilder body = new StringBuilder(""
+"\n"
+" String result = new ToStringBuilder(this).\n"
+""
);
for (ObjectModelAttribute attr : input.getAttributes()) {
//FIXME possibilité de boucles (non directes)
ObjectModelClass attrEntity = null;
if (model.hasClass(attr.getType())) {
attrEntity = model.getClass(attr.getType());
}
boolean isEntity = attrEntity != null &&
templateHelper.isEntity(attrEntity);
ObjectModelAttribute reverse = attr.getReverseAttribute();
if (isEntity && (reverse == null || !reverse.isNavigable())
&& !attr.hasAssociationClass() || !isEntity) {
String attrName = attr.getName();
String constantName = getConstantName(attrName);
body.append(""
+" append("+constantName+", this."+attrName+").\n"
+""
);
}
}
body.append(""
+" toString();\n"
+" return result;\n"
+" "
);
setOperationBody(operation, body.length() == 0 ? " " : body.toString());
}
// -------------------------------------------------------------------------
// 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);
}
}
}