Improve Builder's fieldsFrom() javadoc
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / BuilderTemplate.xtend
index 027bac6d555f2016eb3ad2370270c7539692261e..70f4563316541cb55d264e0b322b90900c5f6289 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.mdsal.binding.java.api.generator
 
 import static extension org.apache.commons.text.StringEscapeUtils.escapeJava
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT
+import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.DATA_OBJECT
 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTABLE_AUGMENTATION_NAME
 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTATION_FIELD
 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
@@ -30,22 +30,14 @@ import org.opendaylight.mdsal.binding.model.api.JavaTypeName
 import org.opendaylight.mdsal.binding.model.api.MethodSignature;
 import org.opendaylight.mdsal.binding.model.api.ParameterizedType
 import org.opendaylight.mdsal.binding.model.api.Type
-import org.opendaylight.mdsal.binding.model.util.TypeConstants
-import org.opendaylight.mdsal.binding.model.util.Types
+import org.opendaylight.mdsal.binding.model.ri.TypeConstants
+import org.opendaylight.mdsal.binding.model.ri.Types
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
-import org.opendaylight.yangtools.concepts.Builder
 
 /**
  * Template for generating JAVA builder classes.
  */
 class BuilderTemplate extends AbstractBuilderTemplate {
-    /**
-     * Constant used as suffix for builder name.
-     */
-    package static val BUILDER_STR = "Builder";
-
-    static val BUILDER = JavaTypeName.create(Builder)
-
     val BuilderImplTemplate implTemplate
 
     /**
@@ -71,7 +63,7 @@ class BuilderTemplate extends AbstractBuilderTemplate {
         «wrapToDocumentation(formatDataForJavaDoc(targetType))»
         «targetType.annotations.generateDeprecatedAnnotation»
         «generatedAnnotation»
-        public class «type.name» implements «BUILDER.importedName»<«targetType.importedName»> {
+        public class «type.name» {
 
             «generateFields(false)»
 
@@ -95,7 +87,11 @@ class BuilderTemplate extends AbstractBuilderTemplate {
 
             «generateSetters»
 
-            @«OVERRIDE.importedName»
+            /**
+             * A new {@link «targetType.name»} instance.
+             *
+             * @return A new {@link «targetType.name»} instance.
+             */
             public «targetType.name» build() {
                 return new «type.enclosedTypes.get(0).importedName»(this);
             }
@@ -206,7 +202,7 @@ class BuilderTemplate extends AbstractBuilderTemplate {
          * Set fields from given grouping argument. Valid argument is instance of one of following types:
          * <ul>
          «FOR impl : type.getAllIfcs»
-         * <li>«impl.importedName»</li>
+         *   <li>{@link «impl.importedName»}</li>
          «ENDFOR»
          * </ul>
          *
@@ -255,13 +251,39 @@ class BuilderTemplate extends AbstractBuilderTemplate {
         if (Types.strictTypeEquals(getter.returnType, ownGetterType)) {
             return "this._" + propertyName + " = " + retrieveProperty
         }
-        if (Types.isListType(ownGetterType)) {
-            val itemType = (ownGetterType as ParameterizedType).actualTypeArguments.get(0)
-            return '''
-                this._«propertyName» = «CODEHELPERS.importedName».checkListFieldCast(«itemType.importedName».class, "«propertyName»", «retrieveProperty»)'''
+        if (ownGetterType instanceof ParameterizedType) {
+            val itemType = ownGetterType.actualTypeArguments.get(0)
+            if (Types.isListType(ownGetterType)) {
+                val importedClass = importedClass(itemType)
+                if (importedClass !== null) {
+                    return printPropertySetter(retrieveProperty, propertyName, "checkListFieldCastIdentity", importedClass)
+                }
+                return printPropertySetter(retrieveProperty, propertyName, "checkListFieldCast", itemType.importedName)
+            }
+            if (Types.isSetType(ownGetterType)) {
+                val importedClass = importedClass(itemType)
+                if (importedClass !== null) {
+                    return printPropertySetter(retrieveProperty, propertyName, "checkSetFieldCastIdentity", importedClass)
+                }
+                return printPropertySetter(retrieveProperty, propertyName, "checkSetFieldCast", itemType.importedName)
+            }
+            if (Types.CLASS.equals(ownGetterType)) {
+                return printPropertySetter(retrieveProperty, propertyName, "checkFieldCastIdentity", itemType.identifier.importedName)
+            }
+        }
+        return printPropertySetter(retrieveProperty, propertyName, "checkFieldCast", ownGetterType.importedName)
+    }
+
+    def private printPropertySetter(String retrieveProperty, String propertyName, String checkerName, String className) '''
+            this._«propertyName» = «CODEHELPERS.importedName».«checkerName»(«className».class, "«propertyName»", «retrieveProperty»)'''
+
+    private def importedClass(Type type) {
+        if (type instanceof ParameterizedType) {
+            if (Types.CLASS.equals(type.rawType)) {
+                return type.actualTypeArguments.get(0).identifier.importedName
+            }
         }
-        return '''
-            this._«propertyName» = «CODEHELPERS.importedName».checkFieldCast(«ownGetter.returnType.importedName».class, "«propertyName»", «retrieveProperty»)'''
+        return null
     }
 
     private def List<Type> getBaseIfcs(GeneratedType type) {
@@ -321,7 +343,7 @@ class BuilderTemplate extends AbstractBuilderTemplate {
     def private generateSetter(GeneratedProperty field) {
         val returnType = field.returnType
         if (returnType instanceof ParameterizedType) {
-            if (Types.isListType(returnType)) {
+            if (Types.isListType(returnType) || Types.isSetType(returnType)) {
                 val arguments = returnType.actualTypeArguments
                 if (arguments.isEmpty) {
                     return generateListSetter(field, Types.objectType)
@@ -444,7 +466,7 @@ class BuilderTemplate extends AbstractBuilderTemplate {
     '''
 
     private def createDescription(GeneratedType targetType) {
-        val target = type.importedName
+        val target = targetType.importedName
         return '''
         Class that builds {@link «target»} instances. Overall design of the class is that of a
         <a href="https://en.wikipedia.org/wiki/Fluent_interface">fluent interface</a>, where method chaining is used.
@@ -453,7 +475,7 @@ class BuilderTemplate extends AbstractBuilderTemplate {
         In general, this class is supposed to be used like this template:
         <pre>
           <code>
-            «target» createTarget(int fooXyzzy, int barBaz) {
+            «target» create«target»(int fooXyzzy, int barBaz) {
                 return new «target»Builder()
                     .setFoo(new FooBuilder().setXyzzy(fooXyzzy).build())
                     .setBar(new BarBuilder().setBaz(barBaz).build())
@@ -474,14 +496,13 @@ class BuilderTemplate extends AbstractBuilderTemplate {
               invocation, which is terminated by {@link #build()}, which is then returned from the method</li>
           <li>better understanding by humans, as the scope of mutable state (the builder) is kept to a minimum and is
               very localized</li>
-          <li>better optimization oportunities, as the object scope is minimized in terms of invocation (rather than
+          <li>better optimization opportunities, as the object scope is minimized in terms of invocation (rather than
               method) stack, making <a href="https://en.wikipedia.org/wiki/Escape_analysis">escape analysis</a> a lot
               easier. Given enough compiler (JIT/AOT) prowess, the cost of th builder object can be completely
               eliminated</li>
         </ul>
 
         @see «target»
-        @see «BUILDER.importedName»
     '''
     }
 
@@ -515,14 +536,10 @@ class BuilderTemplate extends AbstractBuilderTemplate {
         «ENDFOR»
     '''
 
-    override protected generateCopyAugmentation(Type implType) {
-        val hashMapRef = JU_HASHMAP.importedName
-        val augmentTypeRef = augmentType.importedName
-        return '''
-            «JU_MAP.importedName»<«CLASS.importedName»<? extends «augmentTypeRef»>, «augmentTypeRef»> aug = base.augmentations();
-            if (!aug.isEmpty()) {
-                this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(aug);
-            }
-        '''
-    }
+    override protected generateCopyAugmentation(Type implType) '''
+       final var aug = base.augmentations();
+       if (!aug.isEmpty()) {
+           this.«AUGMENTATION_FIELD» = new «JU_HASHMAP.importedName»<>(aug);
+       }
+    '''
 }