Merge "Bug 626 - It should be possible to create java doc"
[mdsal.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / BuilderTemplate.xtend
index c97838ed02125b073a37d61ec53d00e2b72d5546..7645504e6c7584a1f1c3d2857e0bc6197383caa2 100644 (file)
@@ -31,6 +31,7 @@ import java.util.Collection
 import org.opendaylight.yangtools.yang.binding.Identifiable
 import com.google.common.collect.Range
 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import com.google.common.collect.ImmutableList
 
 /**
  * Template for generating JAVA builder classes. 
@@ -139,12 +140,12 @@ class BuilderTemplate extends BaseTemplate {
         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
-        */
+    /**
+     * 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)
@@ -176,10 +177,10 @@ class BuilderTemplate extends BaseTemplate {
      * @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>
+     *  <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) {
@@ -204,7 +205,7 @@ class BuilderTemplate extends BaseTemplate {
      * @return string with JAVA source code
      */
     override body() '''
-
+        «wrapToDocumentation(formatDataForJavaDoc(type))»
         public class «type.name»«BUILDER» {
 
             «generateFields(false)»
@@ -213,6 +214,8 @@ class BuilderTemplate extends BaseTemplate {
 
             «generateConstructorsFromIfcs(type)»
 
+            «generateCopyConstructor(false)»
+
             «generateMethodFieldsFrom(type)»
 
             «generateGetters(false)»
@@ -231,7 +234,7 @@ class BuilderTemplate extends BaseTemplate {
 
                 «generateAugmentField(false)»
 
-                «generateConstructor»
+                «generateCopyConstructor(true)»
 
                 «generateGetters(true)»
 
@@ -316,7 +319,7 @@ class BuilderTemplate extends BaseTemplate {
 
     def private generateMethodFieldsFromComment(GeneratedType type) '''
         /**
-         Set fields from given grouping argument. Valid argument is instance of one of following types:
+         *Set fields from given grouping argument. Valid argument is instance of one of following types:
          * <ul>
          «FOR impl : type.getAllIfcs»
          * <li>«impl.fullyQualifiedName»</li>
@@ -501,13 +504,8 @@ class BuilderTemplate extends BaseTemplate {
         }
     '''
 
-    /**
-     * 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) {
+    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»
@@ -522,37 +520,49 @@ class BuilderTemplate extends BaseTemplate {
                     «removeProperty(allProps, field.name)»
                 «ENDFOR»
                 «removeProperty(allProps, "key")»
-                if (builder.getKey() == null) {
+                if (base.getKey() == null) {
                     this._key = new «keyType.importedName»(
                         «FOR keyProp : keyProps SEPARATOR ", "»
-                            builder.«keyProp.getterMethodName»()
+                            base.«keyProp.getterMethodName»()
                         «ENDFOR»
                     );
                     «FOR field : keyProps»
-                        this.«field.fieldName» = builder.«field.getterMethodName»();
+                        this.«field.fieldName» = base.«field.getterMethodName»();
                     «ENDFOR»
                 } else {
-                    this._key = builder.getKey();
+                    this._key = base.getKey();
                     «FOR field : keyProps»
                            this.«field.fieldName» = _key.«field.getterMethodName»();
                     «ENDFOR»
                 }
             «ENDIF»
             «FOR field : allProps»
-                this.«field.fieldName» = builder.«field.getterMethodName»();
+                «IF List.canonicalName.equals(field.returnType.fullyQualifiedName)»
+                    if (base.«field.getterMethodName»() == null || base.«field.getterMethodName»().isEmpty()) {
+                        this.«field.fieldName» = «Collections.importedName».emptyList();
+                    } else {
+                        this.«field.fieldName» = «ImmutableList.importedName».copyOf(base.«field.getterMethodName»());
+                    }
+                «ELSE»
+                    this.«field.fieldName» = base.«field.getterMethodName»();
+                «ENDIF»
             «ENDFOR»
             «IF augmentField != null»
-               switch (builder.«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 = builder.«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»<>(builder.«augmentField.name»);
-                }
+                «IF !impl»if (base instanceof «type.name»«IMPL») {«ENDIF»
+                    «IF !impl»«type.name»«IMPL» _impl = («type.name»«IMPL») base;«ENDIF»
+                    «val prop = if (impl) "base" else "_impl"»
+                    switch («prop».«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 = «prop».«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»<>(«prop».«augmentField.name»);
+                    }
+                «IF !impl»}«ENDIF»
             «ENDIF»
         }
     '''
@@ -733,4 +743,3 @@ class BuilderTemplate extends BaseTemplate {
     '''
 
 }
-