fr.ird.observe.toolkit.eugene.templates.dto.DtoTransformer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eugene-templates Show documentation
Show all versions of eugene-templates Show documentation
ObServe Eugene templates module
The newest version!
package fr.ird.observe.toolkit.eugene.templates.dto;
/*-
* #%L
* ObServe Toolkit :: Eugene Templates
* %%
* Copyright (C) 2008 - 2017 IRD, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import fr.ird.observe.binder.DtoReferenceBinder;
import fr.ird.observe.dto.IdHelper;
import fr.ird.observe.dto.form.FormDefinition;
import fr.ird.observe.dto.reference.DataDtoReferenceDefinition;
import fr.ird.observe.dto.reference.ReferentialDtoReferenceDefinition;
import fr.ird.observe.spi.dto.DtoModuleHelper;
import fr.ird.observe.toolkit.eugene.templates.DtoHelper;
import fr.ird.observe.toolkit.eugene.templates.DtoModel;
import fr.ird.observe.toolkit.eugene.templates.DtoTransformerContext;
import fr.ird.observe.toolkit.eugene.templates.ToolkitTagValues;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.BeanTransformerTagValues;
import org.nuiton.eugene.java.EugeneJavaTagValues;
import org.nuiton.eugene.java.JavaGeneratorUtil;
import org.nuiton.eugene.java.ObjectModelTransformerToJava;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelClassifier;
import org.nuiton.eugene.models.object.ObjectModelInterface;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.util.beans.Binder;
import org.nuiton.util.beans.BinderFactory;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Generates a bean and a helper class around it.
*
* Generates also a model initializer contract which permits you to interact with all selectedClasses of your model.
*
* For example:
*
* GeneratedBoat
* Boat (extends GeneratedBoat)
* GeneratedBoatHelper
* BoatHelper (extends AbstractBoats)
*
*
* @author Tony Chemit - [email protected]
* @plexus.component role="org.nuiton.eugene.Template" role-hint="fr.ird.observe.toolkit.eugene.templates.dto.DtoTransformer"
* @since 3.0
*/
public class DtoTransformer extends ObjectModelTransformerToJava {
private DtoModel dtoModel;
@Override
public void transformFromModel(ObjectModel model) {
super.transformFromModel(model);
dtoModel = new DtoModel(
new EugeneCoreTagValues(),
new EugeneJavaTagValues(),
new BeanTransformerTagValues(),
new ToolkitTagValues(),
getLog(),
model,
getDefaultPackageName());
DtoTransformerContext context = dtoModel.context;
context.report();
String defaultPackageName = getDefaultPackageName();
String modelBeanInitializeClassName = model.getName() + "ModelInitializer";
boolean generateModelInitializer = !getResourcesHelper().isJavaFileInClassPath(defaultPackageName + "." + modelBeanInitializeClassName);
if (generateModelInitializer) {
ObjectModelInterface anInterface = createInterface(modelBeanInitializeClassName, defaultPackageName);
addOperation(anInterface, "start", "void");
addOperation(anInterface, "end", "void");
for (String fqn : context.selectedClassesFqn) {
ObjectModelClass beanClass = context.selectedClassesByFqn.get(fqn);
if (skipForInitializer(getModel().getPackage(beanClass), beanClass)) {
continue;
}
String beanName = context.classesNameTranslation.get(beanClass);
addImport(anInterface, beanName);
addOperation(anInterface, "init" + beanName, "void");
}
}
String modelInitializerRunnerClassName = model.getName() + "ModelInitializerRunner";
boolean generateInitializerRunnerClassName = !getResourcesHelper().isJavaFileInClassPath(defaultPackageName + "." + modelInitializerRunnerClassName);
if (generateInitializerRunnerClassName) {
ObjectModelClass aClass = createClass(modelInitializerRunnerClassName, defaultPackageName);
StringBuilder bodyBuilder = new StringBuilder();
bodyBuilder.append(""
+"\n"
+" initializer.start();"
);
for (String fqn : context.selectedClassesFqn) {
ObjectModelClass beanClass = context.selectedClassesByFqn.get(fqn);
if (skipForInitializer(getModel().getPackage(beanClass), beanClass)) {
continue;
}
String beanName = context.classesNameTranslation.get(beanClass);
addImport(aClass, beanName);
bodyBuilder.append(""
+"\n"
+" initializer.init"+beanName+"();"
);
}
bodyBuilder.append(""
+"\n"
+" initializer.end();"
);
ObjectModelOperation operation = addOperation(aClass, "init", "void", ObjectModelJavaModifier.STATIC);
addParameter(operation, modelBeanInitializeClassName, "initializer");
setOperationBody(operation, bodyBuilder.toString());
}
}
private static boolean skipForInitializer(ObjectModelPackage aPackage, ObjectModelClass beanClass) {
return beanClass.isAbstract() || EugeneCoreTagValues.isSkip(beanClass, aPackage);
}
@Override
public void transformFromClass(ObjectModelClass input) {
ObjectModelPackage aPackage = getPackage(input);
DtoTransformerContext context = dtoModel.context;
if (context.selectedClasses.contains(input)) {
if (EugeneCoreTagValues.isSkip(input, aPackage)) {
return;
}
String prefix = getConstantPrefix(input);
setConstantPrefix(prefix);
String className = context.classesNameTranslation.get(input);
String generatedClassName = "Generated" + className;
boolean generateClass = notFoundInClassPath(input, className);
if (generateClass) {
generateClass(input, className, generatedClassName);
}
boolean generateGeneratedClass = canGenerateAbstractClass(input, generatedClassName);
if (generateGeneratedClass) {
generateGeneratedClass(aPackage, input, generatedClassName, className);
}
boolean generateHelper = dtoModel.helpers.contains(input);
if (generateHelper) {
String helperClassName = dtoModel.helpersNameTranslation.get(input);
String generatedHelperClassName = "Generated" + helperClassName;
if (notFoundInClassPath(input, helperClassName)) {
generateHelper(input, generatedHelperClassName, helperClassName);
}
if (canGenerateAbstractClass(input, generatedHelperClassName)) {
generateGeneratedHelper(aPackage, input, className, generatedHelperClassName);
}
}
}
}
private void generateClass(ObjectModelClass input, String className, String abstractClassName) {
ObjectModelClass output;
if (input.isAbstract()) {
output = createAbstractClass(className, input.getPackageName());
} else {
output = createClass(className, input.getPackageName());
}
setSuperClass(output, abstractClassName);
getLog().debug("will generate " + output.getQualifiedName());
addSerializable(input, output, true);
}
private void generateGeneratedClass(ObjectModelPackage aPackage, ObjectModelClass input, String generatedClassName, String dtoType) {
String superClass = null;
// test if a super class has bean stereotype
boolean superClassIsBean = false;
Collection superclasses = input.getSuperclasses();
if (CollectionUtils.isNotEmpty(superclasses)) {
for (ObjectModelClass superclass : superclasses) {
superClassIsBean = dtoModel.context.selectedClasses.contains(superclass);
if (superClassIsBean) {
superClass = superclass.getPackageName() + "." + dtoModel.context.classesNameTranslation.get(superclass);
break;
}
superClass = superclass.getQualifiedName();
}
}
if (!superClassIsBean) {
// try to find a super class by tag-value
superClass = dtoModel.beanTagValues.getSuperClassTagValue(input, aPackage, model);
if (superClass != null) {
// will act as if super class is a bean
superClassIsBean = true;
}
}
ObjectModelClass output;
output = createAbstractClass(generatedClassName, input.getPackageName());
if (superClass != null) {
setSuperClass(output, superClass);
}
getLog().debug("will generate " + output.getQualifiedName());
addInterfaces(input, output, null);
generateI18nBlockAndConstants(aPackage, input, output);
if (!input.isAbstract()) {
addGetterProducerInterface(output, dtoType, true);
addSetterProducerInterface(output, dtoType, true);
addGetterProducerMethods(output, dtoType, true, "definition().getDtoGetters()");
addSetterProducerMethods(output, dtoType, true, "definition().getDtoSetters()");
String dtoDefinitionType = input.getName() + "DtoDefinition";
addAttribute(output, "DEFINITION", dtoDefinitionType, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.STATIC);
addImport(output, DtoModuleHelper.class);
String dtoTypeSimpleName = GeneratorUtil.getSimpleName(dtoType);
ObjectModelOperation definitionMethod = addOperation(output, "definition", dtoDefinitionType, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL);
setOperationBody(definitionMethod, ""+"\n"
+" if (DEFINITION == null) {\n"
+" DEFINITION = ("+dtoDefinitionType+") DtoModuleHelper.get().getDefinition("+dtoTypeSimpleName+".class);\n"
+" }\n"
+" return DEFINITION;\n"
+" ");
boolean withReference = dtoModel.referenceContext.selectedClasses.contains(input);
if (withReference) {
addReferenceMethods(input, output);
}
boolean withForm = dtoModel.formContext.selectedClasses.contains(input);
if (withForm) {
addFormDefinitionMethod(output, dtoType);
}
}
// Get available properties
List properties = getProperties(input);
boolean usePCS = dtoModel.beanTagValues.isGeneratePropertyChangeSupport(input, aPackage, model);
boolean generateBooleanGetMethods = dtoModel.eugeneTagValues.isGenerateBooleanGetMethods(input, aPackage, model);
boolean generateNotEmptyCollections = dtoModel.beanTagValues.isGenerateNotEmptyCollections(input, aPackage, model);
// Add properties field + javabean methods
for (ObjectModelAttribute attr : properties) {
createProperty(output, attr, usePCS, generateBooleanGetMethods, generateNotEmptyCollections);
}
if (!superClassIsBean) {
addDefaultMethodForNoneBeanSuperClass(output, usePCS, properties);
}
}
private void addReferenceMethods(ObjectModelClass input, ObjectModelClass output) {
ObjectModelPackage aPackage = getPackage(input);
boolean referential = IdHelper.isReferentialFromPackageName(aPackage.getName());
String dtoType = dtoModel.context.classesNameTranslation.get(input);
String fqn = input.getPackageName() + "." + dtoType;
String referenceType = dtoType.replace("Dto", "Reference");
Class builderMethodName = referential ? ReferentialDtoReferenceDefinition.class : DataDtoReferenceDefinition.class;
addImport(output, builderMethodName);
String definitionType = String.format("%s<%s, %s>", builderMethodName.getName(), dtoType, referenceType);
ObjectModelOperation referenceDefinition = addOperation(output, "referenceDefinition", definitionType, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL);
setOperationBody(referenceDefinition, ""+"\n"
+" return definition().toReferenceDefinition();\n"
+" ");
String binderPackageName = DtoReferenceBinder.class.getPackage().getName();
String binderFieldType = DtoHelper.generateBinderName(dtoModel.context.defaultPackage.getName().length(), binderPackageName, fqn, dtoType + "Reference", referential);
addImport(output, binderFieldType);
binderFieldType = JavaGeneratorUtil.getSimpleName(binderFieldType);
ObjectModelOperation referenceBinder = addOperation(output, "referenceBinder", binderFieldType, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL);
setOperationBody(referenceBinder, ""+"\n"
+" return definition().toReferenceBinder();\n"
+" ");
}
private void addFormDefinitionMethod(ObjectModelClass output, String dtoType) {
addImport(output, FormDefinition.class);
String formDefinitionFieldType = String.format("FormDefinition<%s>", dtoType);
ObjectModelOperation formDefinition = addOperation(output, "formDefinition", formDefinitionFieldType, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL, ObjectModelJavaModifier.PUBLIC);
setOperationBody(formDefinition, ""+"\n"
+" return definition().formDefinition();\n"
+" ");
}
private void generateHelper(ObjectModelClass aClass, String abstractClassName, String defaultClassName) {
String packageName = aClass.getPackageName();
ObjectModelClass output = createClass(defaultClassName, packageName);
setSuperClass(output, packageName + "." + abstractClassName);
getLog().debug("will generate " + output.getQualifiedName());
}
private void generateGeneratedHelper(ObjectModelPackage aPackage,
ObjectModelClass aClass,
String typeName,
String abstractClassName) {
ObjectModelClass output = createAbstractClass(abstractClassName, aPackage.getName());
String superClassName = getGeneratedHelperSuperClassName(aPackage, aClass);
if (StringUtils.isNotBlank(superClassName)) {
setSuperClass(output, superClassName);
}
getLog().debug("will generate " + output.getQualifiedName());
addImport(output, Binder.class);
addImport(output, BinderFactory.class);
ObjectModelOperation operation = addOperation(
output,
"typeOf" + typeName,
" Class",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return (Class) "+typeName+".class;\n"
+" "
);
boolean generateConstructors = dtoModel.beanTagValues.isGenerateHelperConstructors(aClass, aPackage, model) && !aClass.isAbstract();
if (generateConstructors) {
generateGeneratedHelperConstructors(output, typeName);
}
generateGeneratedHelperCopyMethods(output, typeName);
boolean generatePredicates = dtoModel.beanTagValues.isGenerateHelperPredicates(aClass, aPackage, model);
if (generatePredicates) {
generateGeneratedHelperPredicates(aClass, output, typeName);
}
boolean generateFunctions = dtoModel.beanTagValues.isGenerateHelperFunctions(aClass, aPackage, model);
if (generateFunctions) {
generateGeneratedHelperFunctions(aClass, output, typeName);
}
}
private void generateGeneratedHelperConstructors(ObjectModelClass output, String typeName) {
ObjectModelOperation operation = addOperation(
output,
"new" + typeName,
typeName,
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return new "+typeName+"();\n"
+" "
);
operation = addOperation(
output,
"new" + typeName,
" BeanType",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "BeanType", "source");
setOperationBody(operation, ""
+"\n"
+" Class sourceType = typeOf"+typeName+"();\n"
+" Binder binder = BinderFactory.newBinder(sourceType);\n"
+" BeanType result = new"+typeName+"(source, binder);\n"
+" return result;\n"
+" "
);
operation = addOperation(
output,
"new" + typeName,
" BeanType",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "BeanType", "source");
addParameter(operation, "Binder", "binder");
setOperationBody(operation, ""
+"\n"
+" BeanType result = (BeanType) new"+typeName+"();\n"
+" binder.copy(source, result);\n"
+" return result;\n"
+" "
);
}
private void generateGeneratedHelperCopyMethods(ObjectModelClass output, String typeName) {
ObjectModelOperation operation = addOperation(
output,
"copy" + typeName,
" void",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "BeanType", "source");
addParameter(operation, "BeanType", "target");
setOperationBody(operation, ""
+"\n"
+" Class sourceType = typeOf"+typeName+"();\n"
+" Binder binder = BinderFactory.newBinder(sourceType);\n"
+" binder.copy(source, target);\n"
+" "
);
operation = addOperation(
output,
"copy" + typeName,
" void",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "BeanType", "source");
addParameter(operation, "BeanType", "target");
addParameter(operation, "Binder", "binder");
setOperationBody(operation, ""
+"\n"
+" binder.copy(source, target);\n"
+" "
);
}
private void generateGeneratedHelperPredicates(ObjectModelClass input, ObjectModelClass output, String typeName) {
boolean atLeastOnePropertyFound = false;
for (ObjectModelAttribute attribute : getProperties(input)) {
boolean multiple = JavaGeneratorUtil.isNMultiplicity(attribute);
if (multiple) {
continue;
}
atLeastOnePropertyFound = true;
String attrName = getAttributeName(attribute);
String attrType = getAttributeTypeWithGeneric(attribute);
addImport(output, attrType);
String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
String capitalizeAttrName = JavaGeneratorUtil.capitalizeJavaBeanPropertyName(attrName);
String newPreficateMethodName = "new" + capitalizeAttrName + "Predicate";
ObjectModelOperation operation;
operation = addOperation(
output,
newPreficateMethodName,
" Predicate",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, simpleType, attrName);
String getterName = getGetterName(attribute, attrName);
if (dtoModel.context.useJava8) {
setOperationBody(operation, ""
+"\n"
+" return o -> Objects.equals("+attrName+", o."+getterName+"());\n"
+"\n"
+" "
);
} else {
setOperationBody(operation, ""
+"\n"
+" final "+simpleType+" $tmp = "+attrName+";\n"
+" return new Predicate() {\n"
+"\n"
+" @Override\n"
+" public boolean apply(BeanType input) {\n"
+" return Objects.equal($tmp, input."+getterName+"());\n"
+" }\n"
+" };\n"
+"\n"
+" "
);
}
operation = addOperation(
output,
"filterBy" + capitalizeAttrName,
" List",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "Collection", "$source");
addParameter(operation, simpleType, attrName);
if (dtoModel.context.useJava8) {
setOperationBody(operation, ""
+"\n"
+" return $source.stream().filter("+newPreficateMethodName+"("+attrName+")).collect(Collectors.toList());\n"
+" "
);
} else {
addImport(output, Collection.class);
addImport(output, List.class);
addImport(output, Lists.class);
setOperationBody(operation, ""
+"\n"
+" return Lists.newArrayList(Iterables.filter($source, "+newPreficateMethodName+"("+attrName+")));\n"
+" "
);
}
}
if (atLeastOnePropertyFound) {
if (dtoModel.context.useJava8) {
addImport(output, Collection.class);
addImport(output, List.class);
addImport(output, "java.util.Objects");
addImport(output, "java.util.function.Predicate");
addImport(output, "java.util.stream.Collectors");
} else {
addImport(output, com.google.common.base.Objects.class);
addImport(output, com.google.common.base.Predicate.class);
addImport(output, com.google.common.collect.Iterables.class);
}
addImport(output, Iterable.class);
}
}
private void generateGeneratedHelperFunctions(ObjectModelClass input, ObjectModelClass output, String typeName) {
boolean atLeastOnePropertyFound = false;
boolean useJava8 = dtoModel.context.useJava8;
for (ObjectModelAttribute attribute : getProperties(input)) {
boolean multiple = JavaGeneratorUtil.isNMultiplicity(attribute);
if (multiple) {
continue;
}
atLeastOnePropertyFound = true;
String attrName = getAttributeName(attribute);
String attrType = getAttributeTypeWithGeneric(attribute);
addImport(output, attrType);
String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
simpleType = wrapPrimitiveType(simpleType);
String capitalizeAttrName = JavaGeneratorUtil.capitalizeJavaBeanPropertyName(attrName);
String getterName = getGetterName(attribute, attrName);
String newFunctionMethodName = "new" + capitalizeAttrName + "Function";
String getFunctionMethodName = "get" + capitalizeAttrName + "Function";
String functionTypeName = "Function";
String functionFieldName = JavaGeneratorUtil.convertVariableNameToConstantName(capitalizeAttrName + "Function");
addAttribute(
output,
functionFieldName,
"Function<" + typeName + ", " + simpleType + ">",
useJava8 ? typeName + "::" + getterName : newFunctionMethodName + "()",
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.STATIC,
useJava8 ? ObjectModelJavaModifier.PUBLIC : ObjectModelJavaModifier.PROTECTED
);
if (!useJava8) {
ObjectModelOperation operation = addOperation(
output,
getFunctionMethodName,
" " + functionTypeName,
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return ("+functionTypeName+") "+functionFieldName+";\n"
+"\n"
+" "
);
operation = addOperation(
output,
newFunctionMethodName,
" " + functionTypeName,
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return new "+functionTypeName+"() {\n"
+"\n"
+" @Override\n"
+" public "+simpleType+" apply(BeanType input) {\n"
+" return input."+getterName+"();\n"
+" }\n"
+" };\n"
+"\n"
+""
);
}
ObjectModelOperation operation = addOperation(
output,
"uniqueIndexBy" + capitalizeAttrName,
" ImmutableMap<" + simpleType + ", BeanType>",
ObjectModelJavaModifier.STATIC,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "Iterable", "$source");
if (useJava8) {
setOperationBody(operation, ""
+"\n"
+" return Maps.uniqueIndex($source, "+functionFieldName+"::apply);\n"
+" "
);
} else {
setOperationBody(operation, ""
+"\n"
+" return Maps.uniqueIndex($source, "+functionFieldName+");\n"
+" "
);
}
}
if (atLeastOnePropertyFound) {
if (useJava8) {
addImport(output, "java.util.function.Function");
addImport(output, "java.util.Objects");
} else {
addImport(output, Function.class);
addImport(output, com.google.common.collect.Iterables.class);
addImport(output, com.google.common.base.Objects.class);
}
addImport(output, ImmutableMap.class);
addImport(output, Iterable.class);
addImport(output, Maps.class);
}
}
private String getGeneratedHelperSuperClassName(ObjectModelPackage aPackage, ObjectModelClass aClass) {
String superClassName = null;
// test if a super class has bean stereotype
boolean superClassIsBean = false;
Collection superclasses = aClass.getSuperclasses();
if (CollectionUtils.isNotEmpty(superclasses)) {
for (ObjectModelClass superclass : superclasses) {
superClassIsBean = dtoModel.helpers.contains(superclass);
if (superClassIsBean) {
superClassName = superclass.getPackageName() + "." + dtoModel.helpersNameTranslation.get(superclass);
break;
}
superClassName = superclass.getQualifiedName();
}
}
if (!superClassIsBean) {
// try to find a super class by tag-value
superClassName = dtoModel.beanTagValues.getHelperSuperClassTagValue(aClass, aPackage, model);
}
return superClassName;
}
private boolean notFoundInClassPath(ObjectModelClass input, String className) {
String fqn = input.getPackageName() + "." + className;
boolean inClassPath = getResourcesHelper().isJavaFileInClassPath(fqn);
return !inClassPath;
}
protected String getPropertyType(ObjectModelClass output, ObjectModelAttribute attr) {
boolean multiple = JavaGeneratorUtil.isNMultiplicity(attr);
String attrType = getAttributeTypeWithGeneric(attr);
if (multiple) {
attrType = JavaGeneratorUtil.getAttributeInterfaceType(attr, getAttributeTypeWithGeneric(attr), true);
}
addImport(output, attrType);
return JavaGeneratorUtil.getSimpleName(attrType);
}
private void createProperty(ObjectModelClass output,
ObjectModelAttribute attr,
boolean usePCS,
boolean generateBooleanGetMethods,
boolean generateNotEmptyCollections) {
String attrName = getAttributeName(attr);
String attrType = getAttributeTypeWithGeneric(attr);
boolean multiple = JavaGeneratorUtil.isNMultiplicity(attr);
String constantName = getConstantName(attrName);
String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
if (multiple) {
createGetChildMethod(output, attrName, attrType, simpleType);
createIsEmptyMethod(output, attrName);
createSizeMethod(output, attrName);
createAddChildMethod(output, attrName, attrType, constantName, usePCS);
createAddAllChildrenMethod(output, attrName, attrType, constantName, usePCS);
createRemoveChildMethod(output, attrName, attrType, constantName, usePCS);
createRemoveAllChildrenMethod(output, attrName, attrType, constantName, usePCS);
createContainsChildMethod(output, attrName, attrType, constantName, usePCS);
createContainsAllChildrenMethod(output, attrName, attrType, constantName);
// Change type for Multiple attribute
attrType = JavaGeneratorUtil.getAttributeInterfaceType(attr, getAttributeTypeWithGeneric(attr), true);
simpleType = JavaGeneratorUtil.getSimpleName(attrType);
}
boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(attr);
if (multiple) {
String collectionImplementationType = JavaGeneratorUtil.getAttributeImplementationType(attr, getAttributeTypeWithGeneric(attr), true);
// creates a getXXX (multiple) method
createGetMethod(output,
attrName,
attrType,
JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX,
generateNotEmptyCollections,
collectionImplementationType
);
} else {
if (booleanProperty) {
// creates a isXXX method
createGetMethod(output, attrName, attrType, JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX);
}
if (!booleanProperty || generateBooleanGetMethods) {
// creates a getXXX method
createGetMethod(output, attrName, attrType, JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX);
}
}
createSetMethod(output, attrName, attrType, simpleType, constantName, usePCS);
// Add attribute to the class
addAttribute(output, attrName, attrType, "", ObjectModelJavaModifier.PROTECTED);
}
private List getProperties(ObjectModelClass input) {
List attributes =
(List) input.getAttributes();
List attrs =
new ArrayList<>();
for (ObjectModelAttribute attr : attributes) {
if (attr.isNavigable()) {
// only keep navigable attributes
attrs.add(attr);
}
}
return attrs;
}
private List getAllProperties(ObjectModelClass input) {
List attributes =
(List) input.getAllOtherAttributes();
List result = new ArrayList<>();
for (ObjectModelAttribute attr : attributes) {
if (attr.isNavigable()) {
// only keep navigable attributes
result.add(attr);
}
}
result.addAll(getProperties(input));
return result;
}
private void createGetMethod(ObjectModelClass output,
String attrName,
String attrType,
String methodPrefix,
boolean generateLayzCode,
String collectionImplementationType) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName(methodPrefix, attrName),
attrType,
ObjectModelJavaModifier.PUBLIC
);
if (generateLayzCode) {
addImport(output, collectionImplementationType);
String implementationSimpleType = JavaGeneratorUtil.getSimpleName(collectionImplementationType);
setOperationBody(operation, ""
+"\n"
+" if ("+attrName+" == null) {\n"
+" "+attrName+" = new "+implementationSimpleType+"();\n"
+" }\n"
+" return "+attrName+";\n"
+""
);
} else {
setOperationBody(operation, ""
+"\n"
+" return "+attrName+";\n"
+""
);
}
}
private void createGetMethod(ObjectModelClass output,
String attrName,
String attrType,
String methodPrefix) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName(methodPrefix, attrName),
attrType,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return "+attrName+";\n"
+" "
);
}
private void createGetChildMethod(ObjectModelClass output,
String attrName,
String attrType,
String simpleType) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("get", attrName),
attrType,
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "int", "index");
setOperationBody(operation, ""
+"\n"
+" "+simpleType+" o = getChild("+attrName+", index);\n"
+" return o;\n"
+" "
);
}
private void createIsEmptyMethod(ObjectModelClass output,
String attrName) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("is", attrName) + "Empty",
boolean.class,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return "+attrName+" == null || "+attrName+".isEmpty();\n"
+" "
);
}
private void createSizeMethod(ObjectModelClass output,
String attrName) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("size", attrName),
int.class,
ObjectModelJavaModifier.PUBLIC
);
setOperationBody(operation, ""
+"\n"
+" return "+attrName+" == null ? 0 : "+attrName+".size();\n"
+" "
);
}
private void createAddChildMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName,
boolean usePCS) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("add", attrName),
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, attrType, attrName);
String methodName = getJavaBeanMethodName("get", attrName);
StringBuilder buffer = new StringBuilder(""
+"\n"
+" "+methodName+"().add("+attrName+");\n"
+" "
);
if (usePCS) {
buffer.append(""
+" firePropertyChange("+constantName+", null, "+attrName+");\n"
+" "
);
}
setOperationBody(operation, buffer.toString());
}
private void createAddAllChildrenMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName,
boolean usePCS) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("addAll", attrName),
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
String methodName = getJavaBeanMethodName("get", attrName);
StringBuilder buffer = new StringBuilder(""
+"\n"
+" "+methodName+"().addAll("+attrName+");\n"
+" "
);
if (usePCS) {
buffer.append(""
+" firePropertyChange("+constantName+", null, "+attrName+");\n"
+" "
);
}
setOperationBody(operation, buffer.toString());
}
private void createRemoveChildMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName,
boolean usePCS) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("remove", attrName),
"boolean",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, attrType, attrName);
String methodName = getJavaBeanMethodName("get", attrName);
StringBuilder buffer = new StringBuilder();
buffer.append(""
+"\n"
+" boolean removed = "+methodName+"().remove("+attrName+");"
);
if (usePCS) {
buffer.append(""
+"\n"
+" if (removed) {\n"
+" firePropertyChange("+constantName+", "+attrName+", null);\n"
+" }"
);
}
buffer.append(""
+"\n"
+" return removed;\n"
+" "
);
setOperationBody(operation, buffer.toString());
}
private void createRemoveAllChildrenMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName,
boolean usePCS) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("removeAll", attrName),
"boolean",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
StringBuilder buffer = new StringBuilder();
String methodName = getJavaBeanMethodName("get", attrName);
buffer.append(""
+"\n"
+" boolean removed = "+methodName+"().removeAll("+attrName+");"
);
if (usePCS) {
buffer.append(""
+"\n"
+" if (removed) {\n"
+" firePropertyChange("+constantName+", "+attrName+", null);\n"
+" }"
);
}
buffer.append(""
+"\n"
+" return removed;\n"
+" "
);
setOperationBody(operation, buffer.toString());
}
private void createContainsChildMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName,
boolean usePCS) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("contains", attrName),
"boolean",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, attrType, attrName);
StringBuilder buffer = new StringBuilder();
String methodName = getJavaBeanMethodName("get", attrName);
buffer.append(""
+"\n"
+" boolean contains = "+methodName+"().contains("+attrName+");\n"
+" return contains;\n"
+" "
);
setOperationBody(operation, buffer.toString());
}
private void createContainsAllChildrenMethod(ObjectModelClass output,
String attrName,
String attrType,
String constantName) {
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("containsAll", attrName),
"boolean",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
StringBuilder buffer = new StringBuilder();
String methodName = getJavaBeanMethodName("get", attrName);
buffer.append(""
+"\n"
+" boolean contains = "+methodName+"().containsAll("+attrName+");\n"
+" return contains;\n"
+" "
);
setOperationBody(operation, buffer.toString());
}
private void createSetMethod(ObjectModelClass output,
String attrName,
String attrType,
String simpleType,
String constantName,
boolean usePCS) {
boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(simpleType);
ObjectModelOperation operation = addOperation(
output,
getJavaBeanMethodName("set", attrName),
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, attrType, attrName);
if (usePCS) {
String methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX;
if (booleanProperty) {
methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX;
}
String methodName = getJavaBeanMethodName(methodPrefix, attrName);
setOperationBody(operation, ""
+"\n"
+" "+simpleType+" oldValue = "+methodName+"();\n"
+" this."+attrName+" = "+attrName+";\n"
+" firePropertyChange("+constantName+", oldValue, "+attrName+");\n"
+" "
);
} else {
setOperationBody(operation, ""
+"\n"
+" this."+attrName+" = "+attrName+";\n"
+" "
);
}
}
private void addSerializable(ObjectModelClass input, ObjectModelClass output, boolean interfaceFound) {
if (!interfaceFound) {
addInterface(output, Serializable.class);
}
// Generate the serialVersionUID
long serialVersionUID = JavaGeneratorUtil.generateSerialVersionUID(input);
addConstant(output, JavaGeneratorUtil.SERIAL_VERSION_UID, "long", serialVersionUID + "L", ObjectModelJavaModifier.PRIVATE);
}
/**
* Add all interfaces defines in input class and returns if
* {@link Serializable} interface was found.
*
* @param input the input model class to process
* @param output the output generated class
* @return {@code true} if {@link Serializable} was found from input,
* {@code false} otherwise
*/
private boolean addInterfaces(ObjectModelClass input, ObjectModelClassifier output, String extraInterfaceName) {
boolean foundSerializable = false;
Set added = new HashSet<>();
for (ObjectModelInterface parentInterface : input.getInterfaces()) {
String fqn = parentInterface.getQualifiedName();
added.add(fqn);
addInterface(output, fqn);
if (Serializable.class.getName().equals(fqn)) {
foundSerializable = true;
}
}
if (extraInterfaceName != null && !added.contains(extraInterfaceName)) {
addInterface(output, extraInterfaceName);
}
return foundSerializable;
}
private void createPropertyChangeSupport(ObjectModelClass output) {
addAttribute(output,
"pcs",
PropertyChangeSupport.class,
"new PropertyChangeSupport(this)",
ObjectModelJavaModifier.PROTECTED,
ObjectModelJavaModifier.FINAL,
ObjectModelJavaModifier.TRANSIENT
);
// Add PropertyListener
ObjectModelOperation operation;
operation = addOperation(output,
"addPropertyChangeListener",
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, PropertyChangeListener.class, "listener");
setOperationBody(operation, ""
+"\n"
+" pcs.addPropertyChangeListener(listener);\n"
+" "
);
operation = addOperation(output,
"addPropertyChangeListener",
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, String.class, "propertyName");
addParameter(operation, PropertyChangeListener.class, "listener");
setOperationBody(operation, ""
+"\n"
+" pcs.addPropertyChangeListener(propertyName, listener);\n"
+" "
);
operation = addOperation(output,
"removePropertyChangeListener",
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, PropertyChangeListener.class, "listener");
setOperationBody(operation, ""
+"\n"
+" pcs.removePropertyChangeListener(listener);\n"
+" "
);
operation = addOperation(output,
"removePropertyChangeListener",
"void",
ObjectModelJavaModifier.PUBLIC
);
addParameter(operation, String.class, "propertyName");
addParameter(operation, PropertyChangeListener.class, "listener");
setOperationBody(operation, ""
+"\n"
+" pcs.removePropertyChangeListener(propertyName, listener);\n"
+" "
);
operation = addOperation(output,
"firePropertyChange",
"void",
ObjectModelJavaModifier.PROTECTED
);
addParameter(operation, String.class, "propertyName");
addParameter(operation, Object.class, "oldValue");
addParameter(operation, Object.class, "newValue");
setOperationBody(operation, ""
+"\n"
+" pcs.firePropertyChange(propertyName, oldValue, newValue);\n"
+" "
);
operation = addOperation(output,
"firePropertyChange",
"void",
ObjectModelJavaModifier.PROTECTED
);
addParameter(operation, String.class, "propertyName");
addParameter(operation, Object.class, "newValue");
setOperationBody(operation, ""
+"\n"
+" firePropertyChange(propertyName, null, newValue);\n"
+" "
);
}
private void createGetChildMethod(ObjectModelClass output) {
ObjectModelOperation getChild = addOperation(
output,
"getChild", " T",
ObjectModelJavaModifier.PROTECTED
);
addImport(output, List.class);
addParameter(getChild, "java.util.Collection", "childs");
addParameter(getChild, "int", "index");
setOperationBody(getChild, ""
+"\n"
+" T result = null;\n"
+" if (childs != null) {\n"
+" if (childs instanceof List) {\n"
+" if (index < childs.size()) {\n"
+" result = ((List) childs).get(index);\n"
+" }\n"
+" } else {\n"
+" int i = 0;\n"
+" for (T o : childs) {\n"
+" if (index == i) {\n"
+" result = o;\n"
+" break;\n"
+" }\n"
+" i++;\n"
+" }\n"
+" }\n"
+" }\n"
+" return result;\n"
+""
);
}
private void generateI18nBlockAndConstants(ObjectModelPackage aPackage,
ObjectModelClass input,
ObjectModelClassifier output) {
String i18nPrefix = eugeneTagValues.getI18nPrefixTagValue(input,
aPackage,
model);
if (!StringUtils.isEmpty(i18nPrefix)) {
generateI18nBlock(input, output, i18nPrefix);
}
String prefix = getConstantPrefix(input);
setConstantPrefix(prefix);
Set constantNames = addConstantsFromDependency(input, output);
// Add properties constant
for (ObjectModelAttribute attr : getProperties(input)) {
createPropertyConstant(output, attr, prefix, constantNames);
}
}
private void addDefaultMethodForNoneBeanSuperClass(ObjectModelClass output,
boolean usePCS,
List properties) {
if (usePCS) {
// Add property change support
createPropertyChangeSupport(output);
}
boolean hasAMultipleProperty = containsMultiple(properties);
// Add helper operations
if (hasAMultipleProperty) {
// add getChild methods
createGetChildMethod(output);
}
}
private String wrapPrimitiveType(String attrType) {
if (JavaGeneratorUtil.isPrimitiveType(attrType)) {
attrType = JavaGeneratorUtil.getPrimitiveWrapType(attrType);
}
return attrType;
}
private String getGetterName(ObjectModelAttribute attribute, String attrName) {
boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(attribute);
String methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX;
if (booleanProperty) {
methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX;
}
return getJavaBeanMethodName(methodPrefix, attrName);
}
private boolean canGenerateAbstractClass(ObjectModelClass aClass, String abstractClassName) {
boolean inClassPath = !notFoundInClassPath(aClass, abstractClassName);
if (inClassPath) {
throw new IllegalStateException(String.format("Can't generate %s, already found in class-path, this is a generated class, you should not ovveride it.\n\nPlease remove it from class path and use the %s class instead.", aClass.getPackageName() + "." + abstractClassName, aClass));
}
return true;
}
private void createPropertyConstant(ObjectModelClassifier output,
ObjectModelAttribute attr,
String prefix,
Set constantNames) {
String attrName = getAttributeName(attr);
String constantName = prefix + builder.getConstantName(attrName);
if (!constantNames.contains(constantName)) {
addConstant(output,
constantName,
String.class,
"\"" + attrName + "\"",
ObjectModelJavaModifier.PUBLIC
);
}
}
private String getAttributeName(ObjectModelAttribute attr) {
String attrName = attr.getName();
if (attr.hasAssociationClass()) {
String assocAttrName = JavaGeneratorUtil.getAssocAttrName(attr);
attrName = JavaGeneratorUtil.toLowerCaseFirstLetter(assocAttrName);
}
return attrName;
}
private String getAttributeTypeWithGeneric(ObjectModelAttribute attr) {
String attrType = dtoModel.context.getAttributeType(attr);
String generic = eugeneTagValues.getAttributeGenericTagValue(attr);
if (generic != null) {
attrType += String.format("<%s>", dtoModel.context.getAttributeType(generic));
}
return attrType;
}
private boolean containsMultiple(List attributes) {
boolean result = false;
for (ObjectModelAttribute attr : attributes) {
if (JavaGeneratorUtil.isNMultiplicity(attr)) {
result = true;
break;
}
}
return result;
}
}