Remove CRLFs 79/5079/3
authorRobert Varga <rovarga@cisco.com>
Fri, 31 Jan 2014 09:48:20 +0000 (10:48 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 3 Feb 2014 12:01:03 +0000 (12:01 +0000)
Change-Id: I3110b88c70a90797cf699709761c04ab05b7124f
Signed-off-by: Robert Varga <rovarga@cisco.com>
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend

index f626abedadcc15729497203c461e1be88a8a3b4d..274306063c3201d29fc7bd8711ed58150f546262 100644 (file)
  * 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 java.util.Arrays;
+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.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 static org.opendaylight.yangtools.binding.generator.util.Types.*
+import java.util.HashMap
+import java.util.Collections
+import org.opendaylight.yangtools.yang.binding.DataObject
 import java.util.ArrayList
 import java.util.HashSet
 import java.util.Collection
 import org.opendaylight.yangtools.yang.binding.Identifiable
 
-/**\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
+/**
+ * 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 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
+
+    /**
+     * 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)
+    }
+
+    /**
+     * 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)
+        return methods
+    }
+
+    /**
+     * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code> 
+     * and recursivelly 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(Set<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(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() '''
+
+        public class «type.name»«BUILDER» {
+
+            «generateFields(false)»
+
+            «generateConstructorsFromIfcs(type)»
+
+            «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)»
+
+                «generateConstructor»
+
+                «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 generateConstructorFromIfc(Type impl) '''
+        «IF (impl instanceof GeneratedType)»
+            «val implType = impl as GeneratedType»
+
+            «IF !(implType.methodDefinitions.empty)»
+                public «type.name»«BUILDER»(«implType.fullyQualifiedName» arg) {
+                    «printConstructorPropertySetter(implType)»
+                }
+            «ENDIF»
+            «FOR implTypeImplement : implType.implements»
+                «generateConstructorFromIfc(implTypeImplement)»
+            «ENDFOR»
+        «ENDIF»
+    '''
+
+    def private 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.empty»
+            «FOR f : properties»
+                private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
+            «ENDFOR»
+        «ENDIF»
+        «IF augmentField != null»
+            private «Map.importedName»<Class<? 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'»
+            public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {
+                «generateRestrictions(field, "value")»
+
+                this.«field.fieldName» = value;
+                return this;
+            }
+        «ENDFOR»
+        «IF augmentField != null»
+
+            public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(Class<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {
+                this.«augmentField.name».put(augmentationType, augmentation);
+                return this;
+            }
+        «ENDIF»
+    '''
+
+    /**
+     * Template method which generate constructor for IMPL class.
+     * 
+     * @return string with IMPL class constructor
+     */
+    def private generateConstructor() '''
+        private «type.name»«IMPL»(«type.name»«BUILDER» builder) {
+            «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 (builder.getKey() == null) {
+                    this._key = new «keyType.importedName»(
+                        «FOR keyProp : keyProps SEPARATOR ", "»
+                            builder.«keyProp.getterMethodName»()
+                        «ENDFOR»
+                    );
+                    «FOR field : keyProps»
+                        this.«field.fieldName» = builder.«field.getterMethodName»();
+                    «ENDFOR»
+                } else {
+                    this._key = builder.getKey();
+                    «FOR field : keyProps»
+                           this.«field.fieldName» = _key.«field.getterMethodName»();
+                    «ENDFOR»
+                }
+            «ENDIF»
+            «FOR field : allProps»
+                this.«field.fieldName» = builder.«field.getterMethodName»();
+            «ENDFOR»
+            «IF augmentField != null»
+                this.«augmentField.name».putAll(builder.«augmentField.name»);
+            «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<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(java.lang.Object obj) {
+                if (this == obj) {
+                    return true;
+                }
+                if (obj == null) {
+                    return false;
+                }
+                if (getClass() != obj.getClass()) {
+                    return false;
+                }
+                «type.name»«IMPL» other = («type.name»«IMPL») obj;
+                «FOR property : properties»
+                    «val fieldName = property.fieldName»
+                    if («fieldName» == null) {
+                        if (other.«fieldName» != null) {
+                            return false;
+                        }
+                    «IF property.returnType.name.contains("[")»
+                    } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {
+                    «ELSE»
+                    } else if(!«fieldName».equals(other.«fieldName»)) {
+                    «ENDIF»
+                        return false;
+                    }
+                «ENDFOR»
+                «IF augmentField != null»
+                    «val fieldName = augmentField.name»
+                    if («fieldName» == null) {
+                        if (other.«fieldName» != null) {
+                            return false;
+                        }
+                    } else if(!«fieldName».equals(other.«fieldName»)) {
+                        return false;
+                    }
+                «ENDIF»
+                return true;
+            }
+        «ENDIF»
+    '''
+
+    def override generateToString(Collection<GeneratedProperty> properties) '''
+        «IF !properties.empty»
+            @Override
+            public String toString() {
+                StringBuilder builder = new StringBuilder();
+                builder.append("«type.name» [«properties.get(0).fieldName»=");
+                «IF properties.get(0).returnType.name.contains("[")»
+                    builder.append(«Arrays.importedName».toString(«properties.get(0).fieldName»));
+                «ELSE»
+                    builder.append(«properties.get(0).fieldName»);
+                «ENDIF»
+                «FOR i : 1..<properties.size»
+                    builder.append(", «properties.get(i).fieldName»=");
+                    «IF properties.get(i).returnType.name.contains("[")»
+                        builder.append(«Arrays.importedName».toString(«properties.get(i).fieldName»));
+                    «ELSE»
+                        builder.append(«properties.get(i).fieldName»);
+                    «ENDIF»
+                «ENDFOR»
+                «IF augmentField != null»
+                    builder.append(", «augmentField.name»=");
+                    builder.append(«augmentField.name».values());
+                «ENDIF»
+                builder.append("]");
+                return builder.toString();
+            }
+        «ENDIF»
+    '''
+
+    override protected getFullyQualifiedName() {
+        '''«type.fullyQualifiedName»Builder'''.toString
+    }
+
+    def implementedInterfaceGetter() '''
+    public «Class.importedName»<«type.importedName»> getImplementedInterface() {
+        return «type.importedName».class;
+    }
+    '''
+
+}
+