BUG-3051: Fix error reporting string
[mdsal.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / ClassTemplate.xtend
index f75f5a4f58fb72af6316d8076fe7993c9b1824ad..f75299436645bde58056f18eaa925a2270751ef9 100644 (file)
-package org.opendaylight.yangtools.sal.java.api.generator\r
-\r
-import java.util.List\r
-import org.opendaylight.yangtools.binding.generator.util.TypeConstants\r
-import org.opendaylight.yangtools.sal.binding.model.api.Constant\r
-import org.opendaylight.yangtools.sal.binding.model.api.Enumeration\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
-\r
-\r
-/**\r
- * Template for generating JAVA class. \r
- */\r
-class ClassTemplate extends BaseTemplate {\r
-\r
-    protected val List<GeneratedProperty> properties\r
-    protected val List<GeneratedProperty> finalProperties\r
-    protected val List<GeneratedProperty> parentProperties\r
-    protected val Iterable<GeneratedProperty> allProperties;\r
-    \r
-    /**\r
-     * List of enumeration which are generated as JAVA enum type.\r
-     */\r
-    protected val List<Enumeration> enums\r
-    \r
-    /**\r
-     * List of constant instances which are generated as JAVA public static final attributes.\r
-     */\r
-    protected val List<Constant> consts\r
-    \r
-    /**\r
-     * List of generated types which are enclosed inside <code>genType</code>\r
-     */\r
-    protected val List<GeneratedType> enclosedGeneratedTypes;\r
-    \r
-    \r
-    protected val GeneratedTransferObject genTO;\r
-    \r
-    /**\r
-     * Creates instance of this class with concrete <code>genType</code>.\r
-     * \r
-     * @param genType generated transfer object which will be transformed to JAVA class source code\r
-     */\r
-    new(GeneratedTransferObject genType) {\r
-        super(genType)\r
-        this.genTO = genType\r
-        this.properties = genType.properties\r
-        this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)\r
-        this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)\r
-        this.allProperties = properties + parentProperties\r
-        this.enums = genType.enumerations\r
-        this.consts = genType.constantDefinitions\r
-        this.enclosedGeneratedTypes = genType.enclosedTypes\r
-    }\r
-    \r
-\r
-    \r
-    \r
-    \r
-    /**\r
-     * Generates JAVA class source code (class body only).\r
-     * \r
-     * @return string with JAVA class body source code\r
-     */\r
-    def generateAsInnerClass() {\r
-        return generateBody(true)\r
-    }\r
-    \r
-\r
-    \r
-    override protected body() {\r
-        generateBody(false);\r
-    }\r
-\r
-    /**\r
-     * Template method which generates class body.\r
-     * \r
-     * @param isInnerClass boolean value which specify if generated class is|isn't inner\r
-     * @return string with class source code in JAVA format\r
-     */\r
-    def protected generateBody(boolean isInnerClass) '''\r
-        «type.comment.asJavadoc»\r
-        «generateClassDeclaration(isInnerClass)» {\r
-               «innerClassesDeclarations»\r
-            «enumDeclarations»\r
-            «constantsDeclarations»\r
-            «generateFields»\r
-            «constructors»\r
-            «FOR field : properties SEPARATOR "\n"»\r
-                «field.getterMethod»\r
-                «IF !field.readOnly»\r
-                    «field.setterMethod»\r
-                «ENDIF»\r
-            «ENDFOR»\r
-            «generateHashCode»\r
-            «generateEquals»\r
-            «generateToString»\r
-        \r
-        }\r
-    '''\r
-    \r
-    \r
-    /**\r
-     * Template method which generates inner classes inside this interface.\r
-     * \r
-     * @return string with the source code for inner classes in JAVA format\r
-     */\r
-    def protected innerClassesDeclarations() '''\r
-        «IF !enclosedGeneratedTypes.empty»\r
-            «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»\r
-                «IF (innerClass instanceof GeneratedTransferObject)»\r
-                    «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»\r
-                    «classTemplate.generateAsInnerClass»\r
-                    \r
-                «ENDIF»\r
-            «ENDFOR»\r
-        «ENDIF»\r
-    '''\r
-    \r
-    \r
-    def protected constructors() '''\r
-    «allValuesConstructor»\r
-    «IF !allProperties.empty»\r
-    «copyConstructor»\r
-    «ENDIF»\r
-    «IF properties.empty && !parentProperties.empty »\r
-        «parentConstructor»\r
-    «ENDIF»\r
-    '''\r
-    \r
-    def protected allValuesConstructor() '''\r
-    public «type.name»(«allProperties.asArgumentsDeclaration») {\r
-        «IF false == parentProperties.empty»\r
-            super(«parentProperties.asArguments»);\r
-        «ENDIF»\r
-        «FOR p : properties» \r
-            this.«p.fieldName» = «p.fieldName»;\r
-        «ENDFOR»\r
-    }\r
-    '''\r
-    \r
-    \r
-    def protected copyConstructor() '''\r
-    /**\r
-     * Creates a copy from Source Object.\r
-     *\r
-     * @param source Source object\r
-     */\r
-    public «type.name»(«type.name» source) {\r
-        «IF false == parentProperties.empty»\r
-            super(source);\r
-        «ENDIF»\r
-        «FOR p : properties» \r
-            this.«p.fieldName» = source.«p.fieldName»;\r
-        «ENDFOR»\r
-    }\r
-    '''\r
-    \r
-    def protected parentConstructor() '''\r
-    /**\r
-     * Creates a new instance from «genTO.superType.importedName»\r
-     *\r
-     * @param source Source object\r
-     */\r
-    public «type.name»(«genTO.superType.importedName» source) {\r
-            super(source);\r
-    }\r
-    '''\r
-    \r
-\r
-    \r
-    /**\r
-     * Template method which generates JAVA class declaration.\r
-     * \r
-     * @param isInnerClass boolean value which specify if generated class is|isn't inner\r
-     * @return string with class declaration in JAVA format\r
-     */\r
-    def protected generateClassDeclaration(boolean isInnerClass) '''\r
-        public«\r
-        IF (isInnerClass)»«\r
-            " static final "»«\r
-        ELSEIF (type.abstract)»«\r
-            " abstract "»«\r
-        ELSE»«\r
-            " "»«\r
-        ENDIF»class «type.name»«\r
-        IF (genTO.superType != null)»«\r
-            " extends "»«genTO.superType.importedName»«\r
-        ENDIF»\r
-        «IF (!type.implements.empty)»«\r
-            " implements "»«\r
-            FOR type : type.implements SEPARATOR ", "»«\r
-                type.importedName»«\r
-            ENDFOR»«\r
-        ENDIF\r
-    »'''\r
-    \r
-    /**\r
-     * Template method which generates JAVA enum type.\r
-     * \r
-     * @return string with inner enum source code in JAVA format\r
-     */\r
-    def protected enumDeclarations() '''\r
-        «IF !enums.empty»\r
-            «FOR e : enums SEPARATOR "\n"»\r
-                «val enumTemplate = new EnumTemplate(e)»\r
-                «enumTemplate.generateAsInnerClass»\r
-            «ENDFOR»\r
-        «ENDIF»\r
-    '''\r
-    \r
-    /**\r
-     * Template method wich generates JAVA constants.\r
-     * \r
-     * @return string with constants in JAVA format \r
-     */\r
-    def protected constantsDeclarations() '''\r
-        «IF !consts.empty»\r
-            «FOR c : consts»\r
-                «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»\r
-                    «val cValue = c.value»\r
-                    «IF cValue instanceof List<?>»\r
-                        «val cValues = cValue as List<?>»\r
-                        private static final List<Pattern> «Constants.MEMBER_PATTERN_LIST» = new ArrayList<Pattern>();\r
-                        public static final List<String> «TypeConstants.PATTERN_CONSTANT_NAME» = Arrays.asList(«\r
-                        FOR v : cValues SEPARATOR ", "»«\r
-                            IF v instanceof String»"«\r
-                                v as String»"«\r
-                            ENDIF»«\r
-                        ENDFOR»);\r
-                        \r
-                        «generateStaticInicializationBlock»\r
-                    «ENDIF»\r
-                «ELSE»\r
-                    public static final «c.type.importedName» «c.name» = «c.value»;\r
-                «ENDIF»\r
-            «ENDFOR»\r
-        «ENDIF»\r
-    '''\r
-    \r
-    /**\r
-     * Template method which generates JAVA static initialization block.\r
-     * \r
-     * @return string with static initialization block in JAVA format\r
-     */\r
-    def protected generateStaticInicializationBlock() '''\r
-        static {\r
-            for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {\r
-                «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));\r
-            }\r
-        }\r
-    '''\r
-    \r
-    /**\r
-     * Template method which generates JAVA class attributes.\r
-     * \r
-     * @return string with the class attributes in JAVA format\r
-     */\r
-    def protected generateFields() '''\r
-        «IF !properties.empty»\r
-            «FOR f : properties»\r
-                «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»;\r
-            «ENDFOR»\r
-        «ENDIF»\r
-    '''\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 !genTO.hashCodeIdentifiers.empty»\r
-            @Override\r
-            public int hashCode() {\r
-                final int prime = 31;\r
-                int result = 1;\r
-                «FOR property : genTO.hashCodeIdentifiers»\r
-                    result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());\r
-                «ENDFOR»\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 !genTO.equalsIdentifiers.empty»\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» other = («type.name») obj;\r
-                «FOR property : genTO.equalsIdentifiers»\r
-                    «val fieldName = property.fieldName»\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
-                «ENDFOR»\r
-                return true;\r
-            }\r
-        «ENDIF»\r
-    '''\r
-    \r
-    /**\r
-     * Template method which generates the method <code>toString()</code>.\r
-     * \r
-     * @return string with the <code>toString()</code> method definition in JAVA format     \r
-     */\r
-    def protected generateToString() '''\r
-        «IF !genTO.toStringIdentifiers.empty»\r
-            @Override\r
-            public String toString() {\r
-                StringBuilder builder = new StringBuilder();\r
-                «val properties = genTO.toStringIdentifiers»\r
-                builder.append("«type.name» [«properties.get(0).fieldName»=");\r
-                «IF properties.get(0).returnType.name.contains("[")»\r
-                    builder.append(java.util.Arrays.toString(«properties.get(0).fieldName»));\r
-                «ELSE»\r
-                    builder.append(«properties.get(0).fieldName»);\r
-                «ENDIF»\r
-                «FOR i : 1..<genTO.toStringIdentifiers.size»\r
-                    builder.append(", «properties.get(i).fieldName»=");\r
-                    «IF properties.get(i).returnType.name.contains("[")»\r
-                        builder.append(java.util.Arrays.toString(«properties.get(i).fieldName»));\r
-                    «ELSE»\r
-                        builder.append(«properties.get(i).fieldName»);\r
-                    «ENDIF»\r
-                «ENDFOR»\r
-                builder.append("]");\r
-                return builder.toString();\r
-            }\r
-        «ENDIF»\r
-    '''\r
-    \r
-}\r
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * 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
+
+import com.google.common.base.Preconditions
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.Lists
+import com.google.common.collect.Range
+import com.google.common.io.BaseEncoding
+import java.beans.ConstructorProperties
+import java.math.BigDecimal
+import java.math.BigInteger
+import java.util.ArrayList
+import java.util.Arrays
+import java.util.Collections
+import java.util.List
+import java.util.regex.Pattern
+import org.opendaylight.yangtools.binding.generator.util.TypeConstants
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import org.opendaylight.yangtools.sal.binding.model.api.Constant
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+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.Restrictions
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
+
+/**
+ * Template for generating JAVA class.
+ */
+class ClassTemplate extends BaseTemplate {
+
+    protected val List<GeneratedProperty> properties
+    protected val List<GeneratedProperty> finalProperties
+    protected val List<GeneratedProperty> parentProperties
+    protected val Iterable<GeneratedProperty> allProperties;
+    protected val Restrictions restrictions
+
+    /**
+     * List of enumeration which are generated as JAVA enum type.
+     */
+    protected val List<Enumeration> enums
+
+    /**
+     * List of constant instances which are generated as JAVA public static final attributes.
+     */
+    protected val List<Constant> consts
+
+    /**
+     * List of generated types which are enclosed inside <code>genType</code>
+     */
+    protected val List<GeneratedType> enclosedGeneratedTypes;
+
+    protected val GeneratedTransferObject genTO;
+
+    private val AbstractRangeGenerator<?> rangeGenerator
+
+    /**
+     * Creates instance of this class with concrete <code>genType</code>.
+     *
+     * @param genType generated transfer object which will be transformed to JAVA class source code
+     */
+    new(GeneratedTransferObject genType) {
+        super(genType)
+        this.genTO = genType
+        this.properties = genType.properties
+        this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)
+        this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)
+        this.restrictions = genType.restrictions
+
+        var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();
+        sorted.addAll(properties);
+        sorted.addAll(parentProperties);
+        Collections.sort(sorted, [p1, p2|
+            p1.name.compareTo(p2.name)
+        ]);
+
+        this.allProperties = sorted
+        this.enums = genType.enumerations
+        this.consts = genType.constantDefinitions
+        this.enclosedGeneratedTypes = genType.enclosedTypes
+
+        if (restrictions != null && !restrictions.rangeConstraints.nullOrEmpty) {
+            rangeGenerator = AbstractRangeGenerator.forType(findProperty(genType, "value").returnType)
+            Preconditions.checkNotNull(rangeGenerator)
+        } else {
+            rangeGenerator = null
+        }
+    }
+
+    /**
+     * Generates JAVA class source code (class body only).
+     *
+     * @return string with JAVA class body source code
+     */
+    def CharSequence generateAsInnerClass() {
+        return generateBody(true)
+    }
+
+    override protected body() {
+        generateBody(false);
+    }
+
+    /**
+     * Template method which generates class body.
+     *
+     * @param isInnerClass boolean value which specify if generated class is|isn't inner
+     * @return string with class source code in JAVA format
+     */
+    def protected generateBody(boolean isInnerClass) '''
+        «wrapToDocumentation(formatDataForJavaDoc(type))»
+        «generateClassDeclaration(isInnerClass)» {
+            «suidDeclaration»
+            «innerClassesDeclarations»
+            «enumDeclarations»
+            «constantsDeclarations»
+            «generateFields»
+
+            «IF restrictions != null»
+                «IF !restrictions.lengthConstraints.nullOrEmpty»
+                    «LengthGenerator.generateLengthChecker("_value", findProperty(genTO, "value").returnType, restrictions.lengthConstraints)»
+                «ENDIF»
+                «IF !restrictions.rangeConstraints.nullOrEmpty»
+                    «rangeGenerator.generateRangeChecker("_value", restrictions.rangeConstraints)»
+                «ENDIF»
+            «ENDIF»
+
+            «constructors»
+
+            «defaultInstance»
+
+            «FOR field : properties SEPARATOR "\n"»
+                «field.getterMethod»
+                «IF !field.readOnly»
+                    «field.setterMethod»
+                «ENDIF»
+            «ENDFOR»
+
+            «IF (genTO.isTypedef() && genTO.getBaseType instanceof BitsTypeDefinition)»
+                «generateGetValueForBitsTypeDef»
+            «ENDIF»
+
+            «generateHashCode»
+
+            «generateEquals»
+
+            «generateToString(genTO.toStringIdentifiers)»
+
+            «generateLengthMethod()»
+
+            «generateRangeMethod()»
+
+        }
+
+    '''
+
+    /**
+     * Template method which generates the method <code>getValue()</code> for typedef,
+     * which base type is BitsDefinition.
+     *
+     * @return string with the <code>getValue()</code> method definition in JAVA format
+     */
+    def protected generateGetValueForBitsTypeDef() '''
+
+        public boolean[] getValue() {
+            return new boolean[]{
+            «FOR property: genTO.properties SEPARATOR ','»
+                 «property.fieldName»
+            «ENDFOR»
+            };
+        }
+    '''
+
+    @Deprecated
+    def private generateLengthMethod() '''
+        «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
+            «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
+            /**
+             * @deprecated This method is slated for removal in a future release. See BUG-1485 for details.
+             */
+            @Deprecated
+            public static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> length() {
+                «List.importedName»<«Range.importedName»<«numberClass.importedName»>> ret = new java.util.ArrayList<>(«restrictions.lengthConstraints.size»);
+                «FOR r : restrictions.lengthConstraints»
+                    ret.add(«Range.importedName».closed(«numericValue(numberClass, r.min)», «numericValue(numberClass, r.max)»));
+                «ENDFOR»
+                return ret;
+            }
+        «ENDIF»
+    '''
+
+    @Deprecated
+    private def rangeBody(List<RangeConstraint> restrictions, Class<? extends Number> numberClass) '''
+        «List.importedName»<«Range.importedName»<«numberClass.importedName»>> ret = new java.util.ArrayList<>(«restrictions.size»);
+        «FOR r : restrictions»
+            ret.add(«Range.importedName».closed(«numericValue(numberClass, r.min)», «numericValue(numberClass, r.max)»));
+        «ENDFOR»
+    '''
+
+    @Deprecated
+    def private generateRangeMethod() '''
+        «IF restrictions != null && !(restrictions.rangeConstraints.empty)»
+            «val returnType = allProperties.iterator.next.returnType»
+            /**
+             * @deprecated This method is slated for removal in a future release. See BUG-1485 for details.
+             */
+            @Deprecated
+            public static «List.importedName»<«Range.importedName»<«returnType.importedNumber»>> range() {
+            «IF returnType.fullyQualifiedName.equals(BigDecimal.canonicalName)»
+                «rangeBody(restrictions.rangeConstraints, BigDecimal)»
+            «ELSE»
+                «rangeBody(restrictions.rangeConstraints, BigInteger)»
+            «ENDIF»
+                return ret;
+            }
+        «ENDIF»
+    '''
+
+    /**
+     * Template method which generates inner classes inside this interface.
+     *
+     * @return string with the source code for inner classes in JAVA format
+     */
+    def protected innerClassesDeclarations() '''
+        «IF !enclosedGeneratedTypes.empty»
+            «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
+                «IF (innerClass instanceof GeneratedTransferObject)»
+                    «val classTemplate = new ClassTemplate(innerClass)»
+                    «classTemplate.generateAsInnerClass»
+
+                «ENDIF»
+            «ENDFOR»
+        «ENDIF»
+    '''
+
+    def protected constructors() '''
+        «IF genTO.unionType»
+            «genUnionConstructor»
+        «ELSE»
+            «allValuesConstructor»
+        «ENDIF»
+        «IF !allProperties.empty»
+            «copyConstructor»
+        «ENDIF»
+        «IF properties.empty && !parentProperties.empty »
+            «parentConstructor»
+        «ENDIF»
+    '''
+
+    def protected allValuesConstructor() '''
+    «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+        @«ConstructorProperties.importedName»("value")
+    «ENDIF»
+    public «type.name»(«allProperties.asArgumentsDeclaration») {
+        «IF false == parentProperties.empty»
+            super(«parentProperties.asArguments»);
+        «ENDIF»
+        «FOR p : allProperties»
+            «generateRestrictions(type, p.fieldName.toString, p.returnType)»
+        «ENDFOR»
+
+        «/*
+         * If we have patterns, we need to apply them to the value field. This is a sad
+         * consequence of how this code is structured.
+         */
+        IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+
+        «Preconditions.importedName».checkNotNull(_value, "Supplied value may not be null");
+
+            «FOR c : consts»
+                «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME && c.value instanceof List<?>»
+                for (Pattern p : patterns) {
+                    «Preconditions.importedName».checkArgument(p.matcher(_value).matches(), "Supplied value \"%s\" does not match required pattern \"%s\"", _value, p);
+                }
+                «ENDIF»
+            «ENDFOR»
+        «ENDIF»
+
+        «FOR p : properties»
+            «IF p.returnType.importedName.contains("[]")»
+            this.«p.fieldName» = «p.fieldName» == null ? null : «p.fieldName».clone();
+            «ELSE»
+            this.«p.fieldName» = «p.fieldName»;
+            «ENDIF»
+        «ENDFOR»
+    }
+
+    '''
+
+    def protected genUnionConstructor() '''
+    «FOR p : allProperties»
+        «val List<GeneratedProperty> other = new ArrayList(properties)»
+        «IF other.remove(p)»
+            «genConstructor(p, other)»
+        «ENDIF»
+    «ENDFOR»
+
+    '''
+
+    def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''
+    public «type.name»(«property.returnType.importedName + " " + property.name») {
+        «IF false == parentProperties.empty»
+            super(«parentProperties.asArguments»);
+        «ENDIF»
+
+        «generateRestrictions(type, property.fieldName.toString, property.returnType)»
+
+        this.«property.fieldName» = «property.name»;
+        «FOR p : other»
+            this.«p.fieldName» = null;
+        «ENDFOR»
+    }
+    '''
+
+    def private static paramValue(Type returnType, String paramName) {
+        if (returnType instanceof ConcreteType) {
+            return paramName
+        } else {
+            return paramName + ".getValue()"
+        }
+    }
+
+    def private generateRestrictions(Type type, String paramName, Type returnType) '''
+        «val restrictions = type.getRestrictions»
+        «IF restrictions !== null»
+            «IF !restrictions.lengthConstraints.empty || !restrictions.rangeConstraints.empty»
+            if («paramName» != null) {
+                «IF !restrictions.lengthConstraints.empty»
+                    «LengthGenerator.generateLengthCheckerCall(paramName, paramValue(returnType, paramName))»
+                «ENDIF»
+                «IF !restrictions.rangeConstraints.empty»
+                    «rangeGenerator.generateRangeCheckerCall(paramName, paramValue(returnType, paramName))»
+                «ENDIF»
+                }
+            «ENDIF»
+        «ENDIF»
+    '''
+
+    def protected copyConstructor() '''
+    /**
+     * Creates a copy from Source Object.
+     *
+     * @param source Source object
+     */
+    public «type.name»(«type.name» source) {
+        «IF false == parentProperties.empty»
+            super(source);
+        «ENDIF»
+        «FOR p : properties»
+            this.«p.fieldName» = source.«p.fieldName»;
+        «ENDFOR»
+    }
+    '''
+
+    def protected parentConstructor() '''
+    /**
+     * Creates a new instance from «genTO.superType.importedName»
+     *
+     * @param source Source object
+     */
+    public «type.name»(«genTO.superType.importedName» source) {
+            super(source);
+    }
+    '''
+
+    def protected defaultInstance() '''
+        «IF genTO.typedef && !allProperties.empty && !genTO.unionType»
+            «val prop = allProperties.get(0)»
+            «IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))»
+            public static «genTO.name» getDefaultInstance(String defaultValue) {
+                «IF "byte[]".equals(prop.returnType.name)»
+                    «BaseEncoding.importedName» baseEncoding = «BaseEncoding.importedName».base64();
+                    return new «genTO.name»(baseEncoding.decode(defaultValue));
+                «ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(defaultValue);
+                «ELSEIF allProperties.size > 1»
+                    «bitsArgs»
+                «ELSEIF "java.lang.Boolean".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(Boolean.valueOf(defaultValue));
+                «ELSEIF "java.lang.Byte".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(Byte.valueOf(defaultValue));
+                «ELSEIF "java.lang.Short".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(Short.valueOf(defaultValue));
+                «ELSEIF "java.lang.Integer".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(Integer.valueOf(defaultValue));
+                «ELSEIF "java.lang.Long".equals(prop.returnType.fullyQualifiedName)»
+                    return new «genTO.name»(Long.valueOf(defaultValue));
+                «ELSE»
+                    return new «genTO.name»(new «prop.returnType.importedName»(defaultValue));
+                «ENDIF»
+            }
+            «ENDIF»
+        «ENDIF»
+    '''
+
+    def protected bitsArgs() '''
+        «List.importedName»<«String.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
+        if (!properties.contains(defaultValue)) {
+            throw new «IllegalArgumentException.importedName»("invalid default parameter");
+        }
+        int i = 0;
+        return new «genTO.name»(
+        «FOR prop : allProperties SEPARATOR ","»
+            properties.get(i++).equals(defaultValue) ? «Boolean.importedName».TRUE : null
+        «ENDFOR»
+        );
+    '''
+
+    def protected propsAsArgs(Iterable<GeneratedProperty> properties) '''
+        «FOR prop : properties SEPARATOR ","»
+            "«prop.name»"
+        «ENDFOR»
+    '''
+
+    /**
+     * Template method which generates JAVA class declaration.
+     *
+     * @param isInnerClass boolean value which specify if generated class is|isn't inner
+     * @return string with class declaration in JAVA format
+     */
+    def protected generateClassDeclaration(boolean isInnerClass) '''
+        public«
+        IF (isInnerClass)»«
+            " static final "»«
+        ELSEIF (type.abstract)»«
+            " abstract "»«
+        ELSE»«
+            " "»«
+        ENDIF»class «type.name»«
+        IF (genTO.superType != null)»«
+            " extends "»«genTO.superType.importedName»«
+        ENDIF»
+        «IF (!type.implements.empty)»«
+            " implements "»«
+            FOR type : type.implements SEPARATOR ", "»«
+                type.importedName»«
+            ENDFOR»«
+        ENDIF
+    »'''
+
+    /**
+     * Template method which generates JAVA enum type.
+     *
+     * @return string with inner enum source code in JAVA format
+     */
+    def protected enumDeclarations() '''
+        «IF !enums.empty»
+            «FOR e : enums SEPARATOR "\n"»
+                «val enumTemplate = new EnumTemplate(e)»
+                «enumTemplate.generateAsInnerClass»
+            «ENDFOR»
+        «ENDIF»
+    '''
+
+    def protected suidDeclaration() '''
+        «IF genTO.SUID != null»
+            private static final long serialVersionUID = «genTO.SUID.value»L;
+        «ENDIF»
+    '''
+
+    /**
+     * Template method which generates JAVA constants.
+     *
+     * @return string with constants in JAVA format
+     */
+    def protected constantsDeclarations() '''
+        «IF !consts.empty»
+            «FOR c : consts»
+                «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
+                    «val cValue = c.value»
+                    «IF cValue instanceof List<?>»
+                        private static final «Pattern.importedName»[] «Constants.MEMBER_PATTERN_LIST»;
+                        public static final «List.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «ImmutableList.importedName».of(«
+                        FOR v : cValue SEPARATOR ", "»«
+                            IF v instanceof String»"«
+                                v»"«
+                            ENDIF»«
+                        ENDFOR»);
+
+                        «generateStaticInicializationBlock»
+                    «ENDIF»
+                «ELSE»
+                    public static final «c.type.importedName» «c.name» = «c.value»;
+                «ENDIF»
+            «ENDFOR»
+        «ENDIF»
+    '''
+
+    /**
+     * Template method which generates JAVA static initialization block.
+     *
+     * @return string with static initialization block in JAVA format
+     */
+    def protected generateStaticInicializationBlock() '''
+        static {
+            final «Pattern.importedName» a[] = new «Pattern.importedName»[«TypeConstants.PATTERN_CONSTANT_NAME».size()];
+            int i = 0;
+            for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
+                a[i++] = Pattern.compile(regEx);
+            }
+
+            «Constants.MEMBER_PATTERN_LIST» = a;
+        }
+    '''
+
+    /**
+     * Template method which generates JAVA class attributes.
+     *
+     * @return string with the class attributes in JAVA format
+     */
+    def protected generateFields() '''
+        «IF !properties.empty»
+            «FOR f : properties»
+                private«IF f.readOnly» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
+            «ENDFOR»
+        «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 !genTO.hashCodeIdentifiers.empty»
+            @Override
+            public int hashCode() {
+                final int prime = 31;
+                int result = 1;
+                «FOR property : genTO.hashCodeIdentifiers»
+                    «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»
+                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 !genTO.equalsIdentifiers.empty»
+            @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» other = («type.name») obj;
+                «FOR property : genTO.equalsIdentifiers»
+                    «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»
+                return true;
+            }
+        «ENDIF»
+    '''
+
+    def GeneratedProperty getPropByName(String name) {
+        for (GeneratedProperty prop : allProperties) {
+            if (prop.name.equals(name)) {
+                return prop;
+            }
+        }
+        return null;
+    }
+
+}