* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.yangtools.sal.java.api.generator\r
-\r
-import java.util.Arrays;\r
-import java.util.LinkedHashSet\r
-import java.util.List\r
-import java.util.Map\r
-import java.util.Set\r
-import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl\r
-import org.opendaylight.yangtools.binding.generator.util.Types\r
-import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl\r
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty\r
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject\r
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType\r
-import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature\r
-import org.opendaylight.yangtools.sal.binding.model.api.Type\r
-import org.opendaylight.yangtools.yang.binding.Augmentable\r
-import static org.opendaylight.yangtools.binding.generator.util.Types.*\r
-import java.util.HashMap\r
-import java.util.Collections\rimport org.opendaylight.yangtools.yang.binding.DataObject
+package org.opendaylight.yangtools.sal.java.api.generator
+
+import com.google.common.collect.ImmutableSortedSet
+import com.google.common.collect.Range
import java.util.ArrayList
-import java.util.HashSet
+import java.util.Arrays
import java.util.Collection
+import java.util.Collections
+import java.util.HashMap
+import java.util.HashSet
+import java.util.LinkedHashSet
+import java.util.List
+import java.util.Map
+import java.util.Set
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.binding.Augmentable
+import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.Identifiable
+import org.opendaylight.yangtools.concepts.Builder
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder
+
+/**
+ * Template for generating JAVA builder classes.
+ */
+
+class BuilderTemplate extends BaseTemplate {
+
+ /**
+ * Constant with the name of the concrete method.
+ */
+ val static GET_AUGMENTATION_METHOD_NAME = "getAugmentation"
+
+ /**
+ * Constant with the suffix for builder classes.
+ */
+ val static BUILDER = 'Builder'
+
+ /**
+ * Constant with the name of the BuilderFor interface
+ */
+ val static BUILDERFOR = Builder.simpleName;
+
+ /**
+ * Constant with suffix for the classes which are generated from the builder classes.
+ */
+ val static IMPL = 'Impl'
+
+ /**
+ * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME
+ */
+ var GeneratedProperty augmentField
+
+ /**
+ * Set of class attributes (fields) which are derived from the getter methods names
+ */
+ val Set<GeneratedProperty> properties
+
+ private static val METHOD_COMPARATOR = new AlphabeticallyTypeMemberComparator<MethodSignature>();
+
+ /**
+ * Constructs new instance of this class.
+ * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
+ */
+ new(GeneratedType genType) {
+ super(genType)
+ this.properties = propertiesFromMethods(createMethods)
+ importMap.put(Builder.simpleName, Builder.package.name)
+ }
+
+ /**
+ * Returns set of method signature instances which contains all the methods of the <code>genType</code>
+ * and all the methods of the implemented interfaces.
+ *
+ * @returns set of method signature instances
+ */
+ def private Set<MethodSignature> createMethods() {
+ val Set<MethodSignature> methods = new LinkedHashSet();
+ methods.addAll(type.methodDefinitions)
+ collectImplementedMethods(methods, type.implements)
+ val Set<MethodSignature> sortedMethods = ImmutableSortedSet.orderedBy(METHOD_COMPARATOR).addAll(methods).build()
+
+ return sortedMethods
+ }
+
+ /**
+ * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code>
+ * and recursively their implemented interfaces.
+ *
+ * @param methods set of method signatures
+ * @param implementedIfcs list of implemented interfaces
+ */
+ def private void collectImplementedMethods(Set<MethodSignature> methods, List<Type> implementedIfcs) {
+ if (implementedIfcs == null || implementedIfcs.empty) {
+ return
+ }
+ for (implementedIfc : implementedIfcs) {
+ if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
+ val ifc = implementedIfc as GeneratedType
+ methods.addAll(ifc.methodDefinitions)
+ collectImplementedMethods(methods, ifc.implements)
+ } else if (implementedIfc.fullyQualifiedName == Augmentable.name) {
+ for (m : Augmentable.methods) {
+ if (m.name == GET_AUGMENTATION_METHOD_NAME) {
+ val fullyQualifiedName = m.returnType.name
+ val pkg = fullyQualifiedName.package
+ val name = fullyQualifiedName.name
+ val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)
+ val refType = new ReferencedTypeImpl(pkg, name)
+ val generic = new ReferencedTypeImpl(type.packageName, type.name)
+ val parametrizedReturnType = Types.parameterizedTypeFor(refType, generic)
+ tmpGenTO.addMethod(m.name).setReturnType(parametrizedReturnType)
+ augmentField = tmpGenTO.toInstance.methodDefinitions.first.propertyFromGetter
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the first element of the list <code>elements</code>.
+ *
+ * @param list of elements
+ */
+ def private <E> first(List<E> elements) {
+ elements.get(0)
+ }
+
+ /**
+ * Returns the name of the package from <code>fullyQualifiedName</code>.
+ *
+ * @param fullyQualifiedName string with fully qualified type name (package + type)
+ * @return string with the package name
+ */
+ def private String getPackage(String fullyQualifiedName) {
+ val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
+ return if (lastDotIndex == -1) "" else fullyQualifiedName.substring(0, lastDotIndex)
+ }
+
+ /**
+ * Returns the name of tye type from <code>fullyQualifiedName</code>
+ *
+ * @param fullyQualifiedName string with fully qualified type name (package + type)
+ * @return string with the name of the type
+ */
+ def private String getName(String fullyQualifiedName) {
+ val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
+ return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)
+ }
+
+ /**
+ * Creates set of generated property instances from getter <code>methods</code>.
+ *
+ * @param set of method signature instances which should be transformed to list of properties
+ * @return set of generated property instances which represents the getter <code>methods</code>
+ */
+ def private propertiesFromMethods(Collection<MethodSignature> methods) {
+ if (methods == null || methods.isEmpty()) {
+ return Collections.emptySet
+ }
+ val Set<GeneratedProperty> result = new LinkedHashSet
+ for (m : methods) {
+ val createdField = m.propertyFromGetter
+ if (createdField != null) {
+ result.add(createdField)
+ }
+ }
+ return result
+ }
+
+ /**
+ * Creates generated property instance from the getter <code>method</code> name and return type.
+ *
+ * @param method method signature from which is the method name and return type obtained
+ * @return generated property instance for the getter <code>method</code>
+ * @throws IllegalArgumentException<ul>
+ * <li>if the <code>method</code> equals <code>null</code></li>
+ * <li>if the name of the <code>method</code> equals <code>null</code></li>
+ * <li>if the name of the <code>method</code> is empty</li>
+ * <li>if the return type of the <code>method</code> equals <code>null</code></li>
+ * </ul>
+ */
+ def private GeneratedProperty propertyFromGetter(MethodSignature method) {
+ if (method == null || method.name == null || method.name.empty || method.returnType == null) {
+ throw new IllegalArgumentException("Method, method name, method return type reference cannot be NULL or empty!")
+ }
+ var prefix = "get";
+ if(Types.BOOLEAN.equals(method.returnType)) {
+ prefix = "is";
+ }
+ if (method.name.startsWith(prefix)) {
+ val fieldName = method.getName().substring(prefix.length()).toFirstLower
+ val tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo")
+ tmpGenTO.addProperty(fieldName).setReturnType(method.returnType)
+ return tmpGenTO.toInstance.properties.first
+ }
+ }
+
+ /**
+ * Template method which generates JAVA class body for builder class and for IMPL class.
+ *
+ * @return string with JAVA source code
+ */
+ override body() '''
+ «wrapToDocumentation(formatDataForJavaDoc(type))»
+ public class «type.name»«BUILDER» implements «BUILDERFOR» <«type.importedName»> {
+
+ «generateFields(false)»
+
+ «generateAugmentField(false)»
+
+ «generateConstructorsFromIfcs(type)»
+
+ «generateCopyConstructor(false)»
+
+ «generateMethodFieldsFrom(type)»
+
+ «generateGetters(false)»
+
+ «generateSetters»
+
+ public «type.name» build() {
+ return new «type.name»«IMPL»(this);
+ }
+
+ private static final class «type.name»«IMPL» implements «type.name» {
+
+ «implementedInterfaceGetter»
+
+ «generateFields(true)»
+
+ «generateAugmentField(true)»
+
+ «generateCopyConstructor(true)»
+
+ «generateGetters(true)»
+
+ «generateHashCode()»
+
+ «generateEquals()»
+
+ «generateToString(properties)»
+ }
+
+ }
+ '''
+
+ /**
+ * Generate default constructor and constructor for every implemented interface from uses statements.
+ */
+ def private generateConstructorsFromIfcs(Type type) '''
+ public «type.name»«BUILDER»() {
+ }
+ «IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»
+ «val ifc = type as GeneratedType»
+ «FOR impl : ifc.implements»
+ «generateConstructorFromIfc(impl)»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ /**
+ * Generate constructor with argument of given type.
+ */
+ def private Object generateConstructorFromIfc(Type impl) '''
+ «IF (impl instanceof GeneratedType)»
+ «IF !(impl.methodDefinitions.empty)»
+ public «type.name»«BUILDER»(«impl.fullyQualifiedName» arg) {
+ «printConstructorPropertySetter(impl)»
+ }
+ «ENDIF»
+ «FOR implTypeImplement : impl.implements»
+ «generateConstructorFromIfc(implTypeImplement)»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ def private Object printConstructorPropertySetter(Type implementedIfc) '''
+ «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
+ «val ifc = implementedIfc as GeneratedType»
+ «FOR getter : ifc.methodDefinitions»
+ this._«getter.propertyNameFromGetter» = arg.«getter.name»();
+ «ENDFOR»
+ «FOR impl : ifc.implements»
+ «printConstructorPropertySetter(impl)»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ /**
+ * Generate 'fieldsFrom' method to set builder properties based on type of given argument.
+ */
+ def private generateMethodFieldsFrom(Type type) '''
+ «IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»
+ «val ifc = type as GeneratedType»
+ «IF ifc.hasImplementsFromUses»
+ «val List<Type> done = ifc.getBaseIfcs»
+ «generateMethodFieldsFromComment(ifc)»
+ public void fieldsFrom(«DataObject.importedName» arg) {
+ boolean isValidArg = false;
+ «FOR impl : ifc.getAllIfcs»
+ «generateIfCheck(impl, done)»
+ «ENDFOR»
+ if (!isValidArg) {
+ throw new IllegalArgumentException(
+ "expected one of: «ifc.getAllIfcs.toListOfNames» \n" +
+ "but was: " + arg
+ );
+ }
+ }
+ «ENDIF»
+ «ENDIF»
+ '''
+
+ def private generateMethodFieldsFromComment(GeneratedType type) '''
+ /**
+ *Set fields from given grouping argument. Valid argument is instance of one of following types:
+ * <ul>
+ «FOR impl : type.getAllIfcs»
+ * <li>«impl.fullyQualifiedName»</li>
+ «ENDFOR»
+ * </ul>
+ *
+ * @param arg grouping object
+ * @throws IllegalArgumentException if given argument is none of valid types
+ */
+ '''
+
+ /**
+ * Method is used to find out if given type implements any interface from uses.
+ */
+ def boolean hasImplementsFromUses(GeneratedType type) {
+ var i = 0
+ for (impl : type.getAllIfcs) {
+ if ((impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)) {
+ i = i + 1
+ }
+ }
+ return i > 0
+ }
+
+ def private generateIfCheck(Type impl, List<Type> done) '''
+ «IF (impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)»
+ «val implType = impl as GeneratedType»
+ if (arg instanceof «implType.fullyQualifiedName») {
+ «printPropertySetter(implType)»
+ isValidArg = true;
+ }
+ «ENDIF»
+ '''
+
+ def private printPropertySetter(Type implementedIfc) '''
+ «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
+ «val ifc = implementedIfc as GeneratedType»
+ «FOR getter : ifc.methodDefinitions»
+ this._«getter.propertyNameFromGetter» = ((«implementedIfc.fullyQualifiedName»)arg).«getter.name»();
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ private def List<Type> getBaseIfcs(GeneratedType type) {
+ val List<Type> baseIfcs = new ArrayList();
+ for (ifc : type.implements) {
+ if (ifc instanceof GeneratedType && !(ifc as GeneratedType).methodDefinitions.empty) {
+ baseIfcs.add(ifc)
+ }
+ }
+ return baseIfcs
+ }
+
+ private def Set<Type> getAllIfcs(Type type) {
+ val Set<Type> baseIfcs = new HashSet()
+ if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+ val ifc = type as GeneratedType
+ for (impl : ifc.implements) {
+ if (impl instanceof GeneratedType && !(impl as GeneratedType).methodDefinitions.empty) {
+ baseIfcs.add(impl)
+ }
+ baseIfcs.addAll(impl.getAllIfcs)
+ }
+ }
+ return baseIfcs
+ }
+
+ private def List<String> toListOfNames(Collection<Type> types) {
+ val List<String> names = new ArrayList
+ for (type : types) {
+ names.add(type.fullyQualifiedName)
+ }
+ return names
+ }
+
+ /**
+ * Template method which generates class attributes.
+ *
+ * @param boolean value which specify whether field is|isn't final
+ * @return string with class attributes and their types
+ */
+ def private generateFields(boolean _final) '''
+ «IF properties !== null»
+ «FOR f : properties»
+ private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
+ «val restrictions = f.returnType.restrictions»
+ «IF !_final && restrictions != null»
+ «IF !(restrictions.lengthConstraints.empty)»
+ private static «List.importedName»<«Range.importedName»<«f.returnType.importedNumber»>> «f.fieldName»_length;
+ «ENDIF»
+ «IF !(restrictions.rangeConstraints.empty)»
+ private static «List.importedName»<«Range.importedName»<«f.returnType.importedNumber»>> «f.fieldName»_range;
+ «ENDIF»
+ «ENDIF»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ def private generateAugmentField(boolean isPrivate) '''
+ «IF augmentField != null»
+ «IF isPrivate»private «ENDIF»«Map.importedName»<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();
+ «ENDIF»
+ '''
+
+ /**
+ * Template method which generates setter methods
+ *
+ * @return string with the setter methods
+ */
+ def private generateSetters() '''
+ «FOR field : properties SEPARATOR '\n'»
+ «val length = field.fieldName + "_length"»
+ «val range = field.fieldName + "_range"»
+ public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {
+ «generateRestrictions(field, "value", length, range)»
+ this.«field.fieldName» = value;
+ return this;
+ }
+ «generateLengthMethod(length, field.returnType, type.name+BUILDER, length)»
+ «generateRangeMethod(range, field.returnType.restrictions, field.returnType, type.name+BUILDER, range)»
+ «ENDFOR»
+ «IF augmentField != null»
+
+ public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {
+ if (augmentation == null) {
+ return remove«augmentField.name.toFirstUpper»(augmentationType);
+ }
+ this.«augmentField.name».put(augmentationType, augmentation);
+ return this;
+ }
+
+ public «type.name»«BUILDER» remove«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType) {
+ this.«augmentField.name».remove(augmentationType);
+ return this;
+ }
+ «ENDIF»
+ '''
+
+ def generateRestrictions(GeneratedProperty field, String paramName, String lengthGetter, String rangeGetter) '''
+ «val Type type = field.returnType»
+ «IF type instanceof ConcreteType»
+ «createRestrictions(type, paramName, type.name.contains("["), lengthGetter, rangeGetter)»
+ «ELSEIF type instanceof GeneratedTransferObject»
+ «createRestrictions(type, paramName, isArrayType(type as GeneratedTransferObject), lengthGetter, rangeGetter)»
+ «ENDIF»
+ '''
+
+ def private createRestrictions(Type type, String paramName, boolean isArray, String lengthGetter, String rangeGetter) '''
+ «val restrictions = type.getRestrictions»
+ «IF restrictions !== null»
+ «val boolean isNestedType = !(type instanceof ConcreteType)»
+ «IF !restrictions.lengthConstraints.empty»
+ «generateLengthRestriction(type, paramName, lengthGetter, isNestedType, isArray)»
+ «ENDIF»
+ «IF !restrictions.rangeConstraints.empty»
+ «generateRangeRestriction(type, paramName, rangeGetter, isNestedType)»
+ «ENDIF»
+ «ENDIF»
+ '''
+
+ def private generateLengthRestriction(Type type, String paramName, String getterName, boolean isNestedType, boolean isArray) '''
+ «val restrictions = type.getRestrictions»
+ if («paramName» != null) {
+ «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
+ «printLengthConstraint(type, clazz, paramName, isNestedType, isArray)»
+ boolean isValidLength = false;
+ for («Range.importedName»<«clazz.importedNumber»> r : «getterName»()) {
+ if (r.contains(_constraint)) {
+ isValidLength = true;
+ }
+ }
+ if (!isValidLength) {
+ throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», «getterName»));
+ }
+ }
+ '''
+
+ def private generateRangeRestriction(Type type, String paramName, String getterName, boolean isNestedType) '''
+ if («paramName» != null) {
+ «printRangeConstraint(type, paramName, isNestedType)»
+ boolean isValidRange = false;
+ for («Range.importedName»<«type.importedNumber»> r : «getterName»()) {
+ if (r.contains(_constraint)) {
+ isValidRange = true;
+ }
+ }
+ if (!isValidRange) {
+ throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», «getterName»));
+ }
+ }
+ '''
+
+ def private CharSequence generateCopyConstructor(boolean impl) '''
+ «IF impl»private«ELSE»public«ENDIF» «type.name»«IF impl»«IMPL»«ELSE»«BUILDER»«ENDIF»(«type.name»«IF impl»«BUILDER»«ENDIF» base) {
+ «val allProps = new ArrayList(properties)»
+ «val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»
+ «val keyType = type.getKey»
+ «IF isList && keyType != null»
+ «val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»
+ «Collections.sort(keyProps,
+ [ p1, p2 |
+ return p1.name.compareTo(p2.name)
+ ])
+ »
+ «FOR field : keyProps»
+ «removeProperty(allProps, field.name)»
+ «ENDFOR»
+ «removeProperty(allProps, "key")»
+ if (base.getKey() == null) {
+ this._key = new «keyType.importedName»(
+ «FOR keyProp : keyProps SEPARATOR ", "»
+ base.«keyProp.getterMethodName»()
+ «ENDFOR»
+ );
+ «FOR field : keyProps»
+ this.«field.fieldName» = base.«field.getterMethodName»();
+ «ENDFOR»
+ } else {
+ this._key = base.getKey();
+ «FOR field : keyProps»
+ this.«field.fieldName» = _key.«field.getterMethodName»();
+ «ENDFOR»
+ }
+ «ENDIF»
+ «FOR field : allProps»
+ this.«field.fieldName» = base.«field.getterMethodName»();
+ «ENDFOR»
+ «IF augmentField != null»
+ «IF impl»
+ switch (base.«augmentField.name».size()) {
+ case 0:
+ this.«augmentField.name» = «Collections.importedName».emptyMap();
+ break;
+ case 1:
+ final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = base.«augmentField.name».entrySet().iterator().next();
+ this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+ break;
+ default :
+ this.«augmentField.name» = new «HashMap.importedName»<>(base.«augmentField.name»);
+ }
+ «ELSE»
+ if (base instanceof «type.name»«IMPL») {
+ «type.name»«IMPL» impl = («type.name»«IMPL») base;
+ this.«augmentField.name» = new «HashMap.importedName»<>(impl.«augmentField.name»);
+ } else if (base instanceof «AugmentationHolder.importedName») {
+ @SuppressWarnings("unchecked")
+ «AugmentationHolder.importedName»<«type.importedName»> casted =(«AugmentationHolder.importedName»<«type.importedName»>) base;
+ this.«augmentField.name» = new «HashMap.importedName»<>(casted.augmentations());
+ }
+ «ENDIF»
+ «ENDIF»
+ }
+ '''
+
+ private def boolean implementsIfc(GeneratedType type, Type impl) {
+ for (Type ifc : type.implements) {
+ if (ifc.equals(impl)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private def Type getKey(GeneratedType type) {
+ for (m : type.methodDefinitions) {
+ if ("getKey".equals(m.name)) {
+ return m.returnType;
+ }
+ }
+ return null;
+ }
+
+ private def void removeProperty(Collection<GeneratedProperty> props, String name) {
+ var GeneratedProperty toRemove = null
+ for (p : props) {
+ if (p.name.equals(name)) {
+ toRemove = p;
+ }
+ }
+ if (toRemove != null) {
+ props.remove(toRemove);
+ }
+ }
+
+ /**
+ * Template method which generate getter methods for IMPL class.
+ *
+ * @return string with getter methods
+ */
+ def private generateGetters(boolean addOverride) '''
+ «IF !properties.empty»
+ «FOR field : properties SEPARATOR '\n'»
+ «IF addOverride»@Override«ENDIF»
+ «field.getterMethod»
+ «ENDFOR»
+ «ENDIF»
+ «IF augmentField != null»
+
+ @SuppressWarnings("unchecked")
+ «IF addOverride»@Override«ENDIF»
+ public <E extends «augmentField.returnType.importedName»> E get«augmentField.name.toFirstUpper»(«Class.importedName»<E> augmentationType) {
+ if (augmentationType == null) {
+ throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
+ }
+ return (E) «augmentField.name».get(augmentationType);
+ }
+ «ENDIF»
+ '''
+
+ /**
+ * Template method which generates the method <code>hashCode()</code>.
+ *
+ * @return string with the <code>hashCode()</code> method definition in JAVA format
+ */
+ def protected generateHashCode() '''
+ «IF !properties.empty || augmentField != null»
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ «FOR property : properties»
+ «IF property.returnType.name.contains("[")»
+ result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»));
+ «ELSE»
+ result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());
+ «ENDIF»
+ «ENDFOR»
+ «IF augmentField != null»
+ result = prime * result + ((«augmentField.name» == null) ? 0 : «augmentField.name».hashCode());
+ «ENDIF»
+ return result;
+ }
+ «ENDIF»
+ '''
+
+ /**
+ * Template method which generates the method <code>equals()</code>.
+ *
+ * @return string with the <code>equals()</code> method definition in JAVA format
+ */
+ def protected generateEquals() '''
+ «IF !properties.empty || augmentField != null»
+ @Override
+ public boolean equals(«Object.importedName» obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof «DataObject.importedName»)) {
+ return false;
+ }
+ if (!«type.importedName».class.equals(((«DataObject.importedName»)obj).getImplementedInterface())) {
+ return false;
+ }
+ «type.importedName» other = («type.importedName»)obj;
+ «FOR property : properties»
+ «val fieldName = property.fieldName»
+ if («fieldName» == null) {
+ if (other.«property.getterMethodName»() != null) {
+ return false;
+ }
+ «IF property.returnType.name.contains("[")»
+ } else if(!«Arrays.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
+ «ELSE»
+ } else if(!«fieldName».equals(other.«property.getterMethodName»())) {
+ «ENDIF»
+ return false;
+ }
+ «ENDFOR»
+ «IF augmentField != null»
+ if (getClass() == obj.getClass()) {
+ // Simple case: we are comparing against self
+ «type.name»«IMPL» otherImpl = («type.name»«IMPL») obj;
+ «val fieldName = augmentField.name»
+ if («fieldName» == null) {
+ if (otherImpl.«fieldName» != null) {
+ return false;
+ }
+ } else if(!«fieldName».equals(otherImpl.«fieldName»)) {
+ return false;
+ }
+ } else {
+ // Hard case: compare our augments with presence there...
+ for («Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e : «augmentField.name».entrySet()) {
+ if (!e.getValue().equals(other.getAugmentation(e.getKey()))) {
+ return false;
+ }
+ }
+ // .. and give the other one the chance to do the same
+ if (!obj.equals(this)) {
+ return false;
+ }
+ }
+ «ENDIF»
+ return true;
+ }
+ «ENDIF»
+ '''
+
+ def override generateToString(Collection<GeneratedProperty> properties) '''
+ «IF !(properties === null)»
+ @Override
+ public «String.importedName» toString() {
+ «StringBuilder.importedName» builder = new «StringBuilder.importedName» ("«type.name» [");
+ boolean first = true;
+
+ «FOR property : properties»
+ if («property.fieldName» != null) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("«property.fieldName»=");
+ «IF property.returnType.name.contains("[")»
+ builder.append(«Arrays.importedName».toString(«property.fieldName»));
+ «ELSE»
+ builder.append(«property.fieldName»);
+ «ENDIF»
+ }
+ «ENDFOR»
+ «IF augmentField != null»
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("«augmentField.name»=");
+ builder.append(«augmentField.name».values());
+ «ENDIF»
+ return builder.append(']').toString();
+ }
+ «ENDIF»
+ '''
+
+ override protected getFullyQualifiedName() {
+ '''«type.fullyQualifiedName»Builder'''.toString
+ }
+
+ def implementedInterfaceGetter() '''
+ public «Class.importedName»<«type.importedName»> getImplementedInterface() {
+ return «type.importedName».class;
+ }
+ '''
+
+ private def createDescription(GeneratedType type) {
+ return '''
+ Class that builds {@link «type.importedName»} instances.
+
+ @see «type.importedName»
+ '''
+ }
+
+ override def protected String formatDataForJavaDoc(GeneratedType type) {
+ val typeDescription = createDescription(type)
+
+ return '''
+ «IF !typeDescription.nullOrEmpty»
+ «typeDescription»
+ «ENDIF»
+ '''.toString
+ }
+}
-/**\r
- * Template for generating JAVA builder classes. \r
- */\r
-\r
-class BuilderTemplate extends BaseTemplate {\r
-\r
- /**\r
- * Constant with the name of the concrete method.\r
- */\r
- val static GET_AUGMENTATION_METHOD_NAME = "getAugmentation"\r
-\r
- /**\r
- * Constant with the suffix for builder classes.\r
- */\r
- val static BUILDER = 'Builder'\r
-\r
- /**\r
- * Constant with suffix for the classes which are generated from the builder classes.\r
- */\r
- val static IMPL = 'Impl'\r
-\r
- /**\r
- * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME\r
- */\r
- var GeneratedProperty augmentField\r
-\r
- /**\r
- * Set of class attributes (fields) which are derived from the getter methods names\r
- */\r
- val Set<GeneratedProperty> properties\r
-\r
- /**\r
- * Constructs new instance of this class.\r
- * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>\r
- */\r
- new(GeneratedType genType) {\r
- super(genType)\r
- this.properties = propertiesFromMethods(createMethods)\r
- }\r
-\r
- /**\r
- * Returns set of method signature instances which contains all the methods of the <code>genType</code>\r
- * and all the methods of the implemented interfaces.\r
- * \r
- * @returns set of method signature instances\r
- */\r
- def private Set<MethodSignature> createMethods() {\r
- val Set<MethodSignature> methods = new LinkedHashSet\r
- methods.addAll(type.methodDefinitions)\r
- collectImplementedMethods(methods, type.implements)\r
- return methods\r
- }\r
-\r
- /**\r
- * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code> \r
- * and recursivelly their implemented interfaces.\r
- * \r
- * @param methods set of method signatures\r
- * @param implementedIfcs list of implemented interfaces\r
- */\r
- def private void collectImplementedMethods(Set<MethodSignature> methods, List<Type> implementedIfcs) {\r
- if (implementedIfcs == null || implementedIfcs.empty) {\r
- return\r
- }\r
- for (implementedIfc : implementedIfcs) {\r
- if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {\r
- val ifc = implementedIfc as GeneratedType\r
- methods.addAll(ifc.methodDefinitions)\r
- collectImplementedMethods(methods, ifc.implements)\r
- } else if (implementedIfc.fullyQualifiedName == Augmentable.name) {\r
- for (m : Augmentable.methods) {\r
- if (m.name == GET_AUGMENTATION_METHOD_NAME) {\r
- val fullyQualifiedName = m.returnType.name\r
- val pkg = fullyQualifiedName.package\r
- val name = fullyQualifiedName.name\r
- val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)\r
- val refType = new ReferencedTypeImpl(pkg, name)\r
- val generic = new ReferencedTypeImpl(type.packageName, type.name)\r
- val parametrizedReturnType = Types.parameterizedTypeFor(refType, generic)\r
- tmpGenTO.addMethod(m.name).setReturnType(parametrizedReturnType)\r
- augmentField = tmpGenTO.toInstance.methodDefinitions.first.propertyFromGetter\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Returns the first element of the list <code>elements</code>.\r
- * \r
- * @param list of elements\r
- */\r
- def private <E> first(List<E> elements) {\r
- elements.get(0)\r
- }\r
-\r
- /**\r
- * Returns the name of the package from <code>fullyQualifiedName</code>.\r
- * \r
- * @param fullyQualifiedName string with fully qualified type name (package + type)\r
- * @return string with the package name\r
- */\r
- def private String getPackage(String fullyQualifiedName) {\r
- val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)\r
- return if (lastDotIndex == -1) "" else fullyQualifiedName.substring(0, lastDotIndex)\r
- }\r
-\r
- /**\r
- * Returns the name of tye type from <code>fullyQualifiedName</code>\r
- * \r
- * @param fullyQualifiedName string with fully qualified type name (package + type)\r
- * @return string with the name of the type\r
- */\r
- def private String getName(String fullyQualifiedName) {\r
- val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)\r
- return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)\r
- }\r
-\r
- /**\r
- * Creates set of generated property instances from getter <code>methods</code>.\r
- * \r
- * @param set of method signature instances which should be transformed to list of properties \r
- * @return set of generated property instances which represents the getter <code>methods</code>\r
- */\r
- def private propertiesFromMethods(Set<MethodSignature> methods) {\r
- if (methods == null || methods.isEmpty()) {\r
- return Collections.emptySet\r
- }\r
- val Set<GeneratedProperty> result = new LinkedHashSet\r
- for (m : methods) {\r
- val createdField = m.propertyFromGetter\r
- if (createdField != null) {\r
- result.add(createdField)\r
- }\r
- }\r
- return result\r
- }\r
-\r
- /**\r
- * Creates generated property instance from the getter <code>method</code> name and return type.\r
- * \r
- * @param method method signature from which is the method name and return type obtained\r
- * @return generated property instance for the getter <code>method</code>\r
- * @throws IllegalArgumentException<ul>\r
- * <li>if the <code>method</code> equals <code>null</code></li>\r
- * <li>if the name of the <code>method</code> equals <code>null</code></li>\r
- * <li>if the name of the <code>method</code> is empty</li>\r
- * <li>if the return type of the <code>method</code> equals <code>null</code></li>\r
- * </ul>\r
- */\r
- def private GeneratedProperty propertyFromGetter(MethodSignature method) {\r
- if (method == null || method.name == null || method.name.empty || method.returnType == null) {\r
- throw new IllegalArgumentException("Method, method name, method return type reference cannot be NULL or empty!")\r
- }\r
- var prefix = "get";\r
- if(BOOLEAN.equals(method.returnType)) {\r
- prefix = "is";\r
- } \r
- if (method.name.startsWith(prefix)) {\r
- val fieldName = method.getName().substring(prefix.length()).toFirstLower\r
- val tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo")\r
- tmpGenTO.addProperty(fieldName).setReturnType(method.returnType)\r
- return tmpGenTO.toInstance.properties.first\r
- }\r
- }\r
-\r
- /**\r
- * Template method which generates JAVA class body for builder class and for IMPL class. \r
- * \r
- * @return string with JAVA source code\r
- */\r
- override body() '''\r
-\r
- public class «type.name»«BUILDER» {\r
-\r
- «generateFields(false)»\r
-\r
- «generateConstructorsFromIfcs(type)»\r
-\r
- «generateMethodFieldsFrom(type)»\r
-\r
- «generateGetters(false)»\r
-\r
- «generateSetters»\r
-\r
- public «type.name» build() {\r
- return new «type.name»«IMPL»(this);\r
- }\r
-\r
- private static final class «type.name»«IMPL» implements «type.name» {\r
-\r
- «implementedInterfaceGetter»\r
-\r
- «generateFields(true)»\r
-\r
- «generateConstructor»\r
-\r
- «generateGetters(true)»\r
-\r
- «generateHashCode()»\r
-\r
- «generateEquals()»\r
- \r
- «generateToString(properties)»\r
- }\r
-\r
- }\r
- '''\r
-\r
- /**\r
- * Generate default constructor and constructor for every implemented interface from uses statements.\r
- */\r
- def private generateConstructorsFromIfcs(Type type) '''\r
- public «type.name»«BUILDER»() {\r
- } \r
- «IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»\r
- «val ifc = type as GeneratedType»\r
- «FOR impl : ifc.implements»\r
- «generateConstructorFromIfc(impl)»\r
- «ENDFOR»\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Generate constructor with argument of given type.\r
- */\r
- def private generateConstructorFromIfc(Type impl) '''\r
- «IF (impl instanceof GeneratedType)»\r
- «val implType = impl as GeneratedType»\r
-\r
- «IF !(implType.methodDefinitions.empty)»\r
- public «type.name»«BUILDER»(«implType.fullyQualifiedName» arg) {\r
- «printConstructorPropertySetter(implType)»\r
- }\r
- «ENDIF»\r
- «FOR implTypeImplement : implType.implements»\r
- «generateConstructorFromIfc(implTypeImplement)»\r
- «ENDFOR»\r
- «ENDIF»\r
- '''\r
-\r
- def private printConstructorPropertySetter(Type implementedIfc) '''\r
- «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
- «val ifc = implementedIfc as GeneratedType»\r
- «FOR getter : ifc.methodDefinitions»\r
- this._«getter.propertyNameFromGetter» = arg.«getter.name»();\r
- «ENDFOR»\r
- «FOR impl : ifc.implements»\r
- «printConstructorPropertySetter(impl)»\r
- «ENDFOR»\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Generate 'fieldsFrom' method to set builder properties based on type of given argument.\r
- */\r
- def private generateMethodFieldsFrom(Type type) '''\r
- «IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»\r
- «val ifc = type as GeneratedType»\r
- «IF ifc.hasImplementsFromUses»\r
- «val List<Type> done = ifc.getBaseIfcs»\r
- «generateMethodFieldsFromComment(ifc)»\r
- public void fieldsFrom(«DataObject.importedName» arg) {\r
- boolean isValidArg = false;\r
- «FOR impl : ifc.getAllIfcs»\r
- «generateIfCheck(impl, done)»\r
- «ENDFOR»\r
- if (!isValidArg) {\r
- throw new IllegalArgumentException(\r
- "expected one of: «ifc.getAllIfcs.toListOfNames» \n" +\r
- "but was: " + arg\r
- );\r
- }\r
- }\r
- «ENDIF»\r
- «ENDIF»\r
- '''\r
-\r
- def private generateMethodFieldsFromComment(GeneratedType type) '''\r
- /**\r
- Set fields from given grouping argument. Valid argument is instance of one of following types:\r
- * <ul>\r
- «FOR impl : type.getAllIfcs»\r
- * <li>«impl.fullyQualifiedName»</li>\r
- «ENDFOR»\r
- * </ul>\r
- *\r
- * @param arg grouping object\r
- * @throws IllegalArgumentException if given argument is none of valid types\r
- */\r
- '''\r
-\r
- /**\r
- * Method is used to find out if given type implements any interface from uses.\r
- */\r
- def boolean hasImplementsFromUses(GeneratedType type) {\r
- var i = 0\r
- for (impl : type.getAllIfcs) {\r
- if ((impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)) {\r
- i = i + 1\r
- }\r
- }\r
- return i > 0\r
- }\r
-\r
- def private generateIfCheck(Type impl, List<Type> done) '''\r
- «IF (impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)»\r
- «val implType = impl as GeneratedType»\r
- if (arg instanceof «implType.fullyQualifiedName») {\r
- «printPropertySetter(implType)»\r
- isValidArg = true;\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- def private printPropertySetter(Type implementedIfc) '''\r
- «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
- «val ifc = implementedIfc as GeneratedType»\r
- «FOR getter : ifc.methodDefinitions»\r
- this._«getter.propertyNameFromGetter» = ((«implementedIfc.fullyQualifiedName»)arg).«getter.name»();\r
- «ENDFOR»\r
- «ENDIF»\r
- '''\r
-\r
- private def List<Type> getBaseIfcs(GeneratedType type) {\r
- val List<Type> baseIfcs = new ArrayList();\r
- for (ifc : type.implements) {\r
- if (ifc instanceof GeneratedType && !(ifc as GeneratedType).methodDefinitions.empty) {\r
- baseIfcs.add(ifc)\r
- }\r
- }\r
- return baseIfcs \r
- }\r
-\r
- private def Set<Type> getAllIfcs(Type type) {\r
- val Set<Type> baseIfcs = new HashSet()\r
- if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {\r
- val ifc = type as GeneratedType\r
- for (impl : ifc.implements) {\r
- if (impl instanceof GeneratedType && !(impl as GeneratedType).methodDefinitions.empty) {\r
- baseIfcs.add(impl)\r
- }\r
- baseIfcs.addAll(impl.getAllIfcs)\r
- }\r
- }\r
- return baseIfcs \r
- }\r
-\r
- private def List<String> toListOfNames(Collection<Type> types) {\r
- val List<String> names = new ArrayList\r
- for (type : types) {\r
- names.add(type.fullyQualifiedName)\r
- }\r
- return names\r
- }\r
-\r
- /**\r
- * Template method which generates class attributes.\r
- * \r
- * @param boolean value which specify whether field is|isn't final\r
- * @return string with class attributes and their types\r
- */\r
- def private generateFields(boolean _final) '''\r
- «IF !properties.empty»\r
- «FOR f : properties»\r
- private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;\r
- «ENDFOR»\r
- «ENDIF»\r
- «IF augmentField != null»\r
- private «Map.importedName»<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Template method which generates setter methods\r
- * \r
- * @return string with the setter methods \r
- */\r
- def private generateSetters() '''\r
- «FOR field : properties SEPARATOR '\n'»\r
- public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {\r
- «generateRestrictions(field, "value")»\r
-\r
- this.«field.fieldName» = value;\r
- return this;\r
- }\r
- «ENDFOR»\r
- «IF augmentField != null»\r
-\r
- public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(Class<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {\r
- this.«augmentField.name».put(augmentationType, augmentation);\r
- return this;\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Template method which generate constructor for IMPL class.\r
- * \r
- * @return string with IMPL class constructor\r
- */\r
- def private generateConstructor() '''\r
- private «type.name»«IMPL»(«type.name»«BUILDER» builder) {\r
- «val allProps = new ArrayList(properties)»\r
- «val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»\r
- «val keyType = type.getKey»\r
- «IF isList && keyType != null»\r
- «val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»\r
- «Collections.sort(keyProps,\r
- [ p1, p2 |\r
- return p1.name.compareTo(p2.name)\r
- ])\r
- »\r
- «FOR field : keyProps»\r
- «removeProperty(allProps, field.name)»\r
- «ENDFOR»\r
- «removeProperty(allProps, "key")»\r
- if (builder.getKey() == null) {\r
- this._key = new «keyType.importedName»(\r
- «FOR keyProp : keyProps SEPARATOR ", "»\r
- builder.«keyProp.getterMethodName»()\r
- «ENDFOR»\r
- );\r
- «FOR field : keyProps»\r
- this.«field.fieldName» = builder.«field.getterMethodName»();\r
- «ENDFOR»\r
- } else {\r
- this._key = builder.getKey();\r
- «FOR field : keyProps»\r
- this.«field.fieldName» = _key.«field.getterMethodName»();\r
- «ENDFOR»\r
- }\r
- «ENDIF»\r
- «FOR field : allProps»\r
- this.«field.fieldName» = builder.«field.getterMethodName»();\r
- «ENDFOR»\r
- «IF augmentField != null»\r
- this.«augmentField.name».putAll(builder.«augmentField.name»);\r
- «ENDIF»\r
- }\r
- '''\r
-\r
- private def boolean implementsIfc(GeneratedType type, Type impl) {\r
- for (Type ifc : type.implements) {\r
- if (ifc.equals(impl)) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- private def Type getKey(GeneratedType type) {\r
- for (m : type.methodDefinitions) {\r
- if ("getKey".equals(m.name)) {\r
- return m.returnType;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private def void removeProperty(Collection<GeneratedProperty> props, String name) {\r
- var GeneratedProperty toRemove = null\r
- for (p : props) {\r
- if (p.name.equals(name)) {\r
- toRemove = p;\r
- }\r
- }\r
- if (toRemove != null) {\r
- props.remove(toRemove);\r
- }\r
- }\r
-\r
- /**\r
- * Template method which generate getter methods for IMPL class.\r
- * \r
- * @return string with getter methods\r
- */\r
- def private generateGetters(boolean addOverride) '''\r
- «IF !properties.empty»\r
- «FOR field : properties SEPARATOR '\n'»\r
- «IF addOverride»@Override«ENDIF»\r
- «field.getterMethod»\r
- «ENDFOR»\r
- «ENDIF»\r
- «IF augmentField != null»\r
-\r
- @SuppressWarnings("unchecked")\r
- «IF addOverride»@Override«ENDIF»\r
- public <E extends «augmentField.returnType.importedName»> E get«augmentField.name.toFirstUpper»(Class<E> augmentationType) {\r
- if (augmentationType == null) {\r
- throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");\r
- }\r
- return (E) «augmentField.name».get(augmentationType);\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Template method which generates the method <code>hashCode()</code>.\r
- * \r
- * @return string with the <code>hashCode()</code> method definition in JAVA format\r
- */\r
- def protected generateHashCode() '''\r
- «IF !properties.empty || augmentField != null»\r
- @Override\r
- public int hashCode() {\r
- final int prime = 31;\r
- int result = 1;\r
- «FOR property : properties»\r
- «IF property.returnType.name.contains("[")»\r
- result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»));\r
- «ELSE»\r
- result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());\r
- «ENDIF»\r
- «ENDFOR»\r
- «IF augmentField != null»\r
- result = prime * result + ((«augmentField.name» == null) ? 0 : «augmentField.name».hashCode());\r
- «ENDIF»\r
- return result;\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- /**\r
- * Template method which generates the method <code>equals()</code>.\r
- * \r
- * @return string with the <code>equals()</code> method definition in JAVA format \r
- */\r
- def protected generateEquals() '''\r
- «IF !properties.empty || augmentField != null»\r
- @Override\r
- public boolean equals(java.lang.Object obj) {\r
- if (this == obj) {\r
- return true;\r
- }\r
- if (obj == null) {\r
- return false;\r
- }\r
- if (getClass() != obj.getClass()) {\r
- return false;\r
- }\r
- «type.name»«IMPL» other = («type.name»«IMPL») obj;\r
- «FOR property : properties»\r
- «val fieldName = property.fieldName»\r
- if («fieldName» == null) {\r
- if (other.«fieldName» != null) {\r
- return false;\r
- }\r
- «IF property.returnType.name.contains("[")»\r
- } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {\r
- «ELSE»\r
- } else if(!«fieldName».equals(other.«fieldName»)) {\r
- «ENDIF»\r
- return false;\r
- }\r
- «ENDFOR»\r
- «IF augmentField != null»\r
- «val fieldName = augmentField.name»\r
- if («fieldName» == null) {\r
- if (other.«fieldName» != null) {\r
- return false;\r
- }\r
- } else if(!«fieldName».equals(other.«fieldName»)) {\r
- return false;\r
- }\r
- «ENDIF»\r
- return true;\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- def override generateToString(Collection<GeneratedProperty> properties) '''\r
- «IF !properties.empty»\r
- @Override\r
- public String toString() {\r
- StringBuilder builder = new StringBuilder();\r
- builder.append("«type.name» [«properties.get(0).fieldName»=");\r
- «IF properties.get(0).returnType.name.contains("[")»\r
- builder.append(«Arrays.importedName».toString(«properties.get(0).fieldName»));\r
- «ELSE»\r
- builder.append(«properties.get(0).fieldName»);\r
- «ENDIF»\r
- «FOR i : 1..<properties.size»\r
- builder.append(", «properties.get(i).fieldName»=");\r
- «IF properties.get(i).returnType.name.contains("[")»\r
- builder.append(«Arrays.importedName».toString(«properties.get(i).fieldName»));\r
- «ELSE»\r
- builder.append(«properties.get(i).fieldName»);\r
- «ENDIF»\r
- «ENDFOR»\r
- «IF augmentField != null»\r
- builder.append(", «augmentField.name»=");\r
- builder.append(«augmentField.name».values());\r
- «ENDIF»\r
- builder.append("]");\r
- return builder.toString();\r
- }\r
- «ENDIF»\r
- '''\r
-\r
- override protected getFullyQualifiedName() {\r
- '''«type.fullyQualifiedName»Builder'''.toString\r
- }\r
-\r
- def implementedInterfaceGetter() '''\r
- public «Class.importedName»<«type.importedName»> getImplementedInterface() {\r
- return «type.importedName».class;\r
- }\r
- '''\r
-\r
-}\r
-\r