This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository eugene. See https://gitlab.nuiton.org/nuiton/eugene.git commit df817ad3134ad3ad23779df54a2109cb1fc71d32 Author: Tony CHEMIT <chemit@codelutin.com> Date: Tue Oct 18 11:26:14 2016 +0200 Introduce a ng bean transformer (Fixes #4071) --- .../org/nuiton/eugene/java/BeanTransformer.java | 760 +++++++++++++++++++++ .../eugene/java/BeanTransformerTagValues.java | 421 ++++++++++++ ...ion.tagvalue.provider.TagValueMetadatasProvider | 1 + .../i18n/eugene-java-templates_en_GB.properties | 11 + .../i18n/eugene-java-templates_fr_FR.properties | 11 + 5 files changed, 1204 insertions(+) diff --git a/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformer.java b/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformer.java new file mode 100644 index 0000000..8d169a7 --- /dev/null +++ b/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformer.java @@ -0,0 +1,760 @@ +package org.nuiton.eugene.java; + +/* + * #%L + * EUGene :: Java templates + * %% + * Copyright (C) 2012 - 2015 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 + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/*{generator option: parentheses = false}*/ +/*{generator option: writeString = +}*/ + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Generates a bean and a helper class around it. + * + * Generates also a model initializer contract which permits you to interact with all classes of your model. + * + * For example: + * <pre> + * GeneratedBoat + * Boat (extends GeneratedBoat) + * GeneratedBoatHelper + * BoatHelper (extends AbstractBoats) + * </pre> + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role="org.nuiton.eugene.Template" role-hint="org.nuiton.eugene.java.BeanTransformer" + * @since 3.0 + */ +public class BeanTransformer extends AbstractJavaBeanTransformer { + + /** Logger. */ + private static final Log log = LogFactory.getLog(BeanTransformer.class); + + ImmutableMap<ObjectModelClass, String> classesNameTranslation; + ImmutableMap<ObjectModelClass, String> helpersNameTranslation; + + ImmutableSet<ObjectModelClass> classes; + ImmutableSet<ObjectModelClass> helpers; + protected boolean useJava8; + + protected final BeanTransformerTagValues beanTagValues; + + public BeanTransformer() { + beanTagValues = new BeanTransformerTagValues(); + } + + @Override + public void transformFromModel(ObjectModel model) { + super.transformFromModel(model); + + useJava8 = isUseJava8(); + ImmutableMap.Builder<ObjectModelClass, String> classesNameTranslationBuilder = new ImmutableMap.Builder<>(); + ImmutableMap.Builder<ObjectModelClass, String> helpersNameTranslationBuilder = new ImmutableMap.Builder<>(); + ImmutableSet.Builder<ObjectModelClass> classesBuilder = new ImmutableSet.Builder<>(); + ImmutableSet.Builder<ObjectModelClass> helpersBuilder = new ImmutableSet.Builder<>(); + + for (ObjectModelClass aClass : model.getClasses()) { + + ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName()); + if (javaTemplatesTagValues.isBean(aClass, aPackage)) { + + classesBuilder.add(aClass); + + String classNamePrefix = beanTagValues.getClassNamePrefixTagValue(aClass, aPackage, model); + String classNameSuffix = beanTagValues.getClassNameSuffixTagValue(aClass, aPackage, model); + + String generateName = generateName(classNamePrefix, aClass.getName(), classNameSuffix); + classesNameTranslationBuilder.put(aClass, generateName); + + boolean canGenerateHelper = beanTagValues.isGenerateHelper(aClass, aPackage, model); + + if (canGenerateHelper) { + + helpersBuilder.add(aClass); + + String helperNamePrefix = beanTagValues.getHelperClassNamePrefixTagValue(aClass, aPackage, model); + String helperNameSuffix = beanTagValues.getHelperClassNameSuffixTagValue(aClass, aPackage, model); + + String generateHelperName = generateName(helperNamePrefix, aClass.getName(), helperNameSuffix); + helpersNameTranslationBuilder.put(aClass, generateHelperName); + + } + + } + } + + classes = classesBuilder.build(); + helpers = helpersBuilder.build(); + classesNameTranslation = classesNameTranslationBuilder.build(); + helpersNameTranslation = helpersNameTranslationBuilder.build(); + + ImmutableMap<String, ObjectModelClass> beanClassesByFqn = Maps.uniqueIndex(classes, new Function<ObjectModelClass, String>() { + + @Override + public String apply(ObjectModelClass input) { + return input.getQualifiedName(); + } + }); + List<String> beanClassesFqn = new ArrayList<>(beanClassesByFqn.keySet()); + Collections.sort(beanClassesFqn); + + 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 : beanClassesFqn) { + ObjectModelClass beanClass = beanClassesByFqn.get(fqn); + String beanName = 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("" +/*{ + initializer.start();}*/ + ); + for (String fqn : beanClassesFqn) { + ObjectModelClass beanClass = beanClassesByFqn.get(fqn); + String beanName = classesNameTranslation.get(beanClass); + addImport(aClass, beanName); + bodyBuilder.append("" +/*{ + initializer.init<%=beanName%>();}*/ + ); + + } + + bodyBuilder.append("" +/*{ + initializer.end();}*/ + ); + ObjectModelOperation operation = addOperation(aClass, "init", "void", ObjectModelJavaModifier.STATIC); + addParameter(operation, modelBeanInitializeClassName, "initializer"); + setOperationBody(operation, bodyBuilder.toString()); + } + + } + + @Override + public void transformFromClass(ObjectModelClass input) { + + ObjectModelPackage aPackage = getPackage(input); + + if (classes.contains(input)) { + + String prefix = getConstantPrefix(input); + setConstantPrefix(prefix); + + String className = classesNameTranslation.get(input); + String generatedClassName = "Generated" + className; + + boolean generateClass = canGenerateClassWithMethods(aPackage, input, className) + && notFoundInClassPath(input, className); + if (generateClass) { + generateClass(input, className, generatedClassName); + } + + boolean generateGeneratedClass = canGenerateAbstractClass(aPackage, input, generatedClassName); + if (generateGeneratedClass) { + generateGeneratedClass(aPackage, input, generatedClassName); + } + + boolean generateHelper = helpers.contains(input); + if (generateHelper) { + + String helperClassName = helpersNameTranslation.get(input); + String generatedHelperClassName = "Generated" + helperClassName; + + if (notFoundInClassPath(input, helperClassName)) { + + generateHelper(input, generatedHelperClassName, helperClassName); + } + + if (canGenerateAbstractClass(aPackage, input, generatedHelperClassName)) { + + generateGeneratedHelper(aPackage, input, className, generatedHelperClassName); + } + + } + + } + + } + + protected ObjectModelClass 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); + + if (log.isDebugEnabled()) { + log.debug("will generate " + output.getQualifiedName()); + } + + addSerializable(input, output, true); + + return output; + } + + protected ObjectModelClass generateGeneratedClass(ObjectModelPackage aPackage, + ObjectModelClass input, + String className) { + + String superClass = null; + + // test if a super class has bean stereotype + boolean superClassIsBean = false; + Collection<ObjectModelClass> superclasses = input.getSuperclasses(); + if (CollectionUtils.isNotEmpty(superclasses)) { + for (ObjectModelClass superclass : superclasses) { + superClassIsBean = classes.contains(superclass); + if (superClassIsBean) { + superClass = superclass.getPackageName() + "." + classesNameTranslation.get(superclass); + break; + } + superClass = superclass.getQualifiedName(); + } + } + + if (!superClassIsBean) { + + // try to find a super class by tag-value + superClass = beanTagValues.getSuperClassTagValue(input, aPackage, model); + if (superClass != null) { + + // will act as if super class is a bean + superClassIsBean = true; + } + } + + ObjectModelClass output; + + output = createAbstractClass(className, input.getPackageName()); + + if (superClass != null) { + setSuperClass(output, superClass); + } + if (log.isDebugEnabled()) { + log.debug("will generate " + output.getQualifiedName()); + } + + boolean serializableFound; + + serializableFound = addInterfaces(input, output, null); + + generateI18nBlockAndConstants(aPackage, input, output); + + addSerializable(input, output, serializableFound || superClassIsBean); + + // Get available properties + List<ObjectModelAttribute> properties = getProperties(input); + + boolean usePCS = !javaTemplatesTagValues.isSkipGeneratePropertyChangeSupport(input, aPackage, model); + boolean generateBooleanGetMethods = eugeneTagValues.isGenerateBooleanGetMethods(input, aPackage, model); + boolean generateNotEmptyCollections = !javaTemplatesTagValues.isSkipGenerateNotEmptyCollections(input, aPackage, model); + + // Add properties field + javabean methods + for (ObjectModelAttribute attr : properties) { + + createProperty(output, + attr, + usePCS, + generateBooleanGetMethods, + generateNotEmptyCollections); + } + + if (!superClassIsBean) { + addDefaultMethodForNoneBeanSuperClass(output, usePCS, properties); + } + return output; + } + + protected void generateHelper(ObjectModelClass aClass, String abstractClassName, String defaultClassName) { + + String packageName = aClass.getPackageName(); + + ObjectModelClass output = createClass(defaultClassName, packageName); + setSuperClass(output, packageName + "." + abstractClassName); + if (log.isDebugEnabled()) { + log.debug("will generate " + output.getQualifiedName()); + } + + } + + protected void generateGeneratedHelper(ObjectModelPackage aPackage, + ObjectModelClass aClass, + String typeName, + String abstractClassName) { + + ObjectModelClass output = createAbstractClass(abstractClassName, aPackage.getName()); + String superClassName = getAbstractDefaultsSuperClassName(aPackage, aClass); + + if (StringUtils.isNotBlank(superClassName)) { + setSuperClass(output, superClassName); + } + + if (log.isDebugEnabled()) { + log.debug("will generate " + output.getQualifiedName()); + } + + addImport(output, Binder.class); + addImport(output, BinderFactory.class); + + ObjectModelOperation operation = addOperation( + output, + "typeOf" + typeName, + "<BeanType extends " + typeName + "> Class<BeanType>", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + setOperationBody(operation, "" + /*{ + return (Class<BeanType>) <%=typeName%>.class; + }*/ + ); + + boolean generateConstructors = beanTagValues.isGenerateHelperConstructors(aClass, aPackage, model) && !aClass.isAbstract(); + if (generateConstructors) { + generateGeneratedHelperConstructors(output, typeName); + } + + generateGeneratedHelperCopyMethods(output, typeName); + + boolean generatePredicates = beanTagValues.isGenerateHelperPredicates(aClass, aPackage, model); + if (generatePredicates) { + generateGeneratedHelperPredicates(aClass, output, typeName); + } + + boolean generateFunctions = beanTagValues.isGenerateHelperFunctions(aClass, aPackage, model); + if (generateFunctions) { + generateGeneratedHelperFunctions(aClass, output, typeName); + } + + } + + protected void generateGeneratedHelperConstructors(ObjectModelClass output, String typeName) { + + ObjectModelOperation operation = addOperation( + output, + "new" + typeName, + typeName, + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + setOperationBody(operation, "" + /*{ + return new <%=typeName%>(); + }*/ + ); + + operation = addOperation( + output, + "new" + typeName, + "<BeanType extends " + typeName + "> BeanType", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "BeanType", "source"); + setOperationBody(operation, "" + /*{ + Class<BeanType> sourceType = typeOf<%=typeName%>(); + Binder<BeanType, BeanType> binder = BinderFactory.newBinder(sourceType); + BeanType result = new<%=typeName%>(source, binder); + return result; + }*/ + ); + + operation = addOperation( + output, + "new" + typeName, + "<BeanType extends " + typeName + "> BeanType", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "BeanType", "source"); + addParameter(operation, "Binder<BeanType, BeanType>", "binder"); + setOperationBody(operation, "" + /*{ + BeanType result = (BeanType) new<%=typeName%>(); + binder.copy(source, result); + return result; + }*/ + ); + + } + + protected void generateGeneratedHelperCopyMethods(ObjectModelClass output, String typeName) { + + ObjectModelOperation operation = addOperation( + output, + "copy" + typeName, + "<BeanType extends " + typeName + "> void", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "BeanType", "source"); + addParameter(operation, "BeanType", "target"); + setOperationBody(operation, "" + /*{ + Class<BeanType> sourceType = typeOf<%=typeName%>(); + Binder<BeanType, BeanType> binder = BinderFactory.newBinder(sourceType); + binder.copy(source, target); + }*/ + ); + + operation = addOperation( + output, + "copy" + typeName, + "<BeanType extends " + typeName + "> void", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "BeanType", "source"); + addParameter(operation, "BeanType", "target"); + addParameter(operation, "Binder<BeanType, BeanType>", "binder"); + setOperationBody(operation, "" + /*{ + binder.copy(source, target); + }*/ + ); + + } + + protected 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, + "<BeanType extends " + typeName + "> Predicate<BeanType>", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, simpleType, attrName); + String getterName = getGetterName(attribute, attrName); + + if (useJava8) { + setOperationBody(operation, "" + /*{ + return o -> Objects.equals(<%=attrName%>, o.<%=getterName%>()); + + }*/ + ); + } else { + setOperationBody(operation, "" + /*{ + final <%=simpleType%> $tmp = <%=attrName%>; + return new Predicate<BeanType>() { + + @Override + public boolean apply(BeanType input) { + return Objects.equals($tmp, input.<%=getterName%>()); + } + }; + + }*/ + ); + } + + operation = addOperation( + output, + "filterBy" + capitalizeAttrName, + "<BeanType extends " + typeName + "> List<BeanType>", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "Collection<BeanType>", "source"); + addParameter(operation, simpleType, attrName); + + if (useJava8) { + setOperationBody(operation, "" + /*{ + return source.stream().filter(<%=newPreficateMethodName%>(<%=attrName%>)).collect(Collectors.toList()); + }*/ + ); + } else { + setOperationBody(operation, "" + /*{ + return Iterables.filter(source, <%=newPreficateMethodName%>(<%=attrName%>)); + }*/ + ); + } + } + + if (atLeastOnePropertyFound) { + if(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); + } + + } + + protected void generateGeneratedHelperFunctions(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); + 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<BeanType, " + simpleType + ">"; + + 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, + "<BeanType extends " + typeName + "> " + functionTypeName, + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + + + setOperationBody(operation, "" + /*{ + return (<%=functionTypeName%>) <%=functionFieldName%>; + + }*/ + ); + + operation = addOperation( + output, + newFunctionMethodName, + "<BeanType extends " + typeName + "> " + functionTypeName, + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + + setOperationBody(operation, "" +/*{ + return new <%=functionTypeName%>() { + + @Override + public <%=simpleType%> apply(BeanType input) { + return input.<%=getterName%>(); + } + }; + +}*/ + ); + } + + ObjectModelOperation operation = addOperation( + output, + "uniqueIndexBy" + capitalizeAttrName, + "<BeanType extends " + typeName + "> ImmutableMap<" + simpleType + ", BeanType>", + ObjectModelJavaModifier.STATIC, + ObjectModelJavaModifier.PUBLIC + ); + addParameter(operation, "Iterable<BeanType>", "source"); + if (useJava8) { + setOperationBody(operation, "" + /*{ + return Maps.uniqueIndex(source, <%=functionFieldName%>::apply); + }*/ + ); + } else { + setOperationBody(operation, "" + /*{ + return Maps.uniqueIndex(source, <%=functionFieldName%>); + }*/ + ); + } + } + + 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); + } + + } + + protected String getAbstractDefaultsSuperClassName(ObjectModelPackage aPackage, ObjectModelClass aClass) { + String superClassName = null; + + // test if a super class has bean stereotype + boolean superClassIsBean = false; + Collection<ObjectModelClass> superclasses = aClass.getSuperclasses(); + if (CollectionUtils.isNotEmpty(superclasses)) { + for (ObjectModelClass superclass : superclasses) { + superClassIsBean = helpers.contains(superclass); + if (superClassIsBean) { + superClassName = superclass.getPackageName() + "." + helpersNameTranslation.get(superclass); + break; + } + superClassName = superclass.getQualifiedName(); + } + } + + if (!superClassIsBean) { + + // try to find a super class by tag-value + superClassName = beanTagValues.getDefaultsSuperClassTagValue(aClass, aPackage, model); + + } + return superClassName; + } + + @Override + protected String getAttributeType(ObjectModelAttribute attr) { + String attrType = super.getAttributeType(attr); + if (!JavaGeneratorUtil.isPrimitiveType(attrType)) { + boolean hasClass = model.hasClass(attrType); + if (hasClass) { + ObjectModelClass attributeClass = model.getClass(attrType); + String attributeType = classesNameTranslation.get(attributeClass); + if (attributeType != null) { + attrType = attributeClass.getPackageName() + "." + attributeType; + } + } + } + return attrType; + } + + protected String getAttributeType(String attrType) { + if (!JavaGeneratorUtil.isPrimitiveType(attrType)) { + boolean hasClass = model.hasClass(attrType); + if (hasClass) { + ObjectModelClass attributeClass = model.getClass(attrType); + String attributeType = classesNameTranslation.get(attributeClass); + if (attributeType != null) { + attrType = attributeClass.getPackageName() + "." + attributeType; + } + } + } + return attrType; + } + +} diff --git a/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformerTagValues.java b/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformerTagValues.java new file mode 100644 index 0000000..ace441e --- /dev/null +++ b/eugene-java-templates/src/main/java/org/nuiton/eugene/java/BeanTransformerTagValues.java @@ -0,0 +1,421 @@ +package org.nuiton.eugene.java; + +/* + * #%L + * EUGene :: Java templates + * %% + * Copyright (C) 2012 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 + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableSet; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.eugene.models.extension.tagvalue.TagValueMetadata; +import org.nuiton.eugene.models.extension.tagvalue.TagValueUtil; +import org.nuiton.eugene.models.extension.tagvalue.matcher.EqualsTagValueNameMatcher; +import org.nuiton.eugene.models.extension.tagvalue.provider.DefaultTagValueMetadatasProvider; +import org.nuiton.eugene.models.object.ObjectModel; +import org.nuiton.eugene.models.object.ObjectModelClassifier; +import org.nuiton.eugene.models.object.ObjectModelPackage; + +import java.util.Set; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * Defines all tag values managed by Java templates. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role="org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider" role-hint="bean" + * @since 2.5.6 + */ +public class BeanTransformerTagValues extends DefaultTagValueMetadatasProvider { + + @Override + public String getDescription() { + return t("eugene.bean.tagvalues"); + } + + public enum Store implements TagValueMetadata { + + /** + * To generate a utility class around the bean. this classe offers functions, predicates, copy methods, ... + * + * You must use it on the complete model. + * + * @see #isGenerateHelper(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + generateHelper(n("eugene.bean.tagvalue.generateHelper"), boolean.class, "true", ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + + /** + * To generate or not guava predicates on each property of the bean. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #isGenerateHelperPredicates(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + generateHelperPredicates(n("eugene.bean.tagvalue.generateHelperPredicates"), boolean.class, "true", ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To generate or not guava functions on each property of the bean. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #isGenerateHelperFunctions(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + generateHelperFunctions(n("eugene.bean.tagvalue.generateHelperFunctions"), boolean.class, "true", ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To generate or not constructors methods on Default classes. + * + * You can globaly use it on the complete model, package or on a specific classifier. + * + * @see #isGenerateHelperConstructors(ObjectModelClassifier, ObjectModelPackage, ObjectModel)} + * @since 3.0 + */ + generateHelperConstructors(n("eugene.bean.tagvalue.generateHelperConstructors"), boolean.class, "true", ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * Tag value to use a super class for generated bean. + * + * If the bean needs Property change support (says you use the tag-value {@link EugeneJavaTagValues.Store#generatePropertyChangeSupport}, + * then your class must provide evrything for it. + * + * More over, if you use some collections in your bean you must also define + * two method named {@code getChild(Collection list, int index)} and + * {@code getChild(List list, int index)} + * + * See new code to know minimum stuff to add in your class for this purpose. + * <pre> + * public abstract class BeanSupport implements Serializable { + * + * private static final long serialVersionUID = 1L; + * + * protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + * + * public void addPropertyChangeListener(PropertyChangeListener listener) { + * pcs.addPropertyChangeListener(listener); + * } + * + * public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + * pcs.addPropertyChangeListener(propertyName, listener); + * } + * + * public void removePropertyChangeListener(PropertyChangeListener listener) { + * pcs.removePropertyChangeListener(listener); + * } + * + * public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + * pcs.removePropertyChangeListener(propertyName, listener); + * } + * + * protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + * pcs.firePropertyChange(propertyName, oldValue, newValue); + * } + * + * protected void firePropertyChange(String propertyName, Object newValue) { + * firePropertyChange(propertyName, null, newValue); + * } + * + * protected <T> T getChild(Collection<T> list, int index) { + * return CollectionUtil.getOrNull(list, index); + * } + * + * protected <T> T getChild(List<T> list, int index) { + * return CollectionUtil.getOrNull(list, index); + * } + * } + * </pre> + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getSuperClassTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + superClass(n("eugene.bean.tagvalue.superClass"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * Tag value to use a super super-class for generated defaults class of a simple bean. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getDefaultsSuperClassTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + helperSuperClass(n("eugene.bean.tagvalue.helperSuperClass"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To add a prefix on the name of each generated bean class. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getClassNamePrefixTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + classNamePrefix(n("eugene.bean.tagvalue.classNamePrefix"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To add a prefix on the name of each generated bean class. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getClassNameSuffixTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + classNameSuffix(n("eugene.bean.tagvalue.classNameSuffix"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To add a prefix on the name of each generated bean class. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getHelperClassNamePrefixTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + helperClassNamePrefix(n("eugene.bean.tagvalue.helperClassNamePrefix"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class), + + /** + * To add a suffix on the name of each generated bean class. + * + * You can globaly use it on the complete model or to a specific classifier. + * + * @see #getHelperClassNameSuffixTagValue(ObjectModelClassifier, ObjectModelPackage, ObjectModel) + * @since 3.0 + */ + helperClassNameSuffix(n("eugene.bean.tagvalue.helperClassNameSuffix"), String.class, null, ObjectModel.class, ObjectModelPackage.class, ObjectModelClassifier.class); + + private final Set<Class<?>> targets; + private final Class<?> type; + private final String i18nDescriptionKey; + private final String defaultValue; + + Store(String i18nDescriptionKey, Class<?> type, String defaultValue, Class<?>... targets) { + this.targets = ImmutableSet.copyOf(targets); + this.type = type; + this.i18nDescriptionKey = i18nDescriptionKey; + this.defaultValue = defaultValue; + } + + @Override + public String getName() { + return name(); + } + + @Override + public Set<Class<?>> getTargets() { + return targets; + } + + @Override + public Class<?> getType() { + return type; + } + + @Override + public Class<EqualsTagValueNameMatcher> getMatcherClass() { + return EqualsTagValueNameMatcher.class; + } + + @Override + public String getDescription() { + return t(i18nDescriptionKey); + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public boolean isDeprecated() { + return false; + } + + } + + public BeanTransformerTagValues() { + super((TagValueMetadata[]) Store.values()); + } + + /** + * Obtain the value of the {@link Store#superClass} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#superClass + * @since 3.0 + */ + public String getSuperClassTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findTagValue(Store.superClass, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#helperSuperClass} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#helperSuperClass + * @since 3.0 + */ + public String getDefaultsSuperClassTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findTagValue(Store.helperSuperClass, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#classNamePrefix} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#classNamePrefix + * @since 3.0 + */ + public String getClassNamePrefixTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findTagValue(Store.classNamePrefix, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#classNameSuffix} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#classNameSuffix + * @since 3.0 + */ + public String getClassNameSuffixTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findTagValue(Store.classNameSuffix, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#helperClassNamePrefix} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#helperClassNamePrefix + * @since 3.0 + */ + public String getHelperClassNamePrefixTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findTagValue(Store.helperClassNamePrefix, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#helperClassNameSuffix} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * <strong>If not filled, then use default {@code s} value.</strong> + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#helperClassNameSuffix + * @since 3.0 + */ + public String getHelperClassNameSuffixTagValue(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + String value = TagValueUtil.findTagValue(Store.helperClassNameSuffix, classifier, aPackage, model); + if (StringUtils.isBlank(value)) { + value = "Helper"; + } + return value; + } + + /** + * Obtain the value of the {@link Store#generateHelper} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#generateHelper + * @since 3.0 + */ + public boolean isGenerateHelper(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findBooleanTagValue(Store.generateHelper, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#generateHelperPredicates} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * <strong>If not filled, then use default {@code s} value.</strong> + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#generateHelperPredicates + * @since 3.0 + */ + public boolean isGenerateHelperPredicates(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findBooleanTagValue(Store.generateHelperPredicates, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#generateHelperFunctions} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * <strong>If not filled, then use default {@code s} value.</strong> + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#generateHelperFunctions + * @since 3.0 + */ + public boolean isGenerateHelperFunctions(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findBooleanTagValue(Store.generateHelperFunctions, classifier, aPackage, model); + } + + /** + * Obtain the value of the {@link Store#generateHelperConstructors} tag value on the given model or classifier. + * + * It will first look on the model, and then in the given classifier. + * + * <strong>If not filled, then use default {@code s} value.</strong> + * + * @param classifier classifier to seek + * @param model model to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see Store#generateHelperConstructors + * @since 3.0 + */ + public boolean isGenerateHelperConstructors(ObjectModelClassifier classifier, ObjectModelPackage aPackage, ObjectModel model) { + return TagValueUtil.findBooleanTagValue(Store.generateHelperConstructors, classifier, aPackage, model); + } + +} diff --git a/eugene-java-templates/src/main/resources/META-INF/services/org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider b/eugene-java-templates/src/main/resources/META-INF/services/org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider index 1c26f8d..ee3ae73 100644 --- a/eugene-java-templates/src/main/resources/META-INF/services/org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider +++ b/eugene-java-templates/src/main/resources/META-INF/services/org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider @@ -1,4 +1,5 @@ org.nuiton.eugene.java.EugeneJavaTagValues +org.nuiton.eugene.java.BeanTransformerTagValues org.nuiton.eugene.java.JavaBeanTransformerTagValues org.nuiton.eugene.java.SimpleJavaBeanTransformerTagValues org.nuiton.eugene.java.SimpleJavaBeanWithNoInterfaceTransformerTagValues diff --git a/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_en_GB.properties b/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_en_GB.properties index 485a515..4ea8cdb 100644 --- a/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_en_GB.properties +++ b/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_en_GB.properties @@ -1,3 +1,14 @@ +eugene.bean.tagvalue.classNamePrefix=Class name's prefix +eugene.bean.tagvalue.classNameSuffix=Class name's suffix +eugene.bean.tagvalue.generateHelper=Generate helper ? +eugene.bean.tagvalue.generateHelperConstructors=Generate helper constructor methods ? +eugene.bean.tagvalue.generateHelperFunctions=Generate helper function methods ? +eugene.bean.tagvalue.generateHelperPredicates=Generate helper predicate methods ? +eugene.bean.tagvalue.helperClassNamePrefix=Helper name's prefix +eugene.bean.tagvalue.helperClassNameSuffix=Helper name's suffix +eugene.bean.tagvalue.helperSuperClass=Helper super-class +eugene.bean.tagvalue.superClass=Bean super-class +eugene.bean.tagvalues=EUGeNe Bean transformer tag values eugene.java.stereotype.acceptBeanWithMethods=Accept methods on bean? eugene.java.stereotype.bean=Is a bean? eugene.java.stereotype.generateNotEmptyCollections=Generate none empty collections? diff --git a/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_fr_FR.properties b/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_fr_FR.properties index 08a7698..86d46c1 100644 --- a/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_fr_FR.properties +++ b/eugene-java-templates/src/main/resources/i18n/eugene-java-templates_fr_FR.properties @@ -1,3 +1,14 @@ +eugene.bean.tagvalue.classNamePrefix=Préfixe du nom de la classe du bean +eugene.bean.tagvalue.classNameSuffix=Suffixe du nom de la classe du bean +eugene.bean.tagvalue.generateHelper=Générer les helper ? +eugene.bean.tagvalue.generateHelperConstructors=Générer les méthodes de constructeurs sur le helper ? +eugene.bean.tagvalue.generateHelperFunctions=Générer les fonctions sur le helper ? +eugene.bean.tagvalue.generateHelperPredicates=Générer les prédicats sur le helper ? +eugene.bean.tagvalue.helperClassNamePrefix=Préfixe du nom de la classe du helper +eugene.bean.tagvalue.helperClassNameSuffix=Suffixe du nom de la classe du helper +eugene.bean.tagvalue.helperSuperClass=Super-classe des helpers +eugene.bean.tagvalue.superClass=Super class des beans +eugene.bean.tagvalues=EUGeNe Bean transformer tag values eugene.java.stereotype.acceptBeanWithMethods=Accepter les beans avec des méthodes ? eugene.java.stereotype.bean=Is a bean ? eugene.java.stereotype.generateNotEmptyCollections=Générer des collections non vides ? -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.