Correct YangModuleInfo.getInstance() nullness warning
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / ClassTemplate.xtend
index 658c341ee2cddd9277854cf4ea024c4c04a0cc35..7000c109fdbe7eac3483b285cef203e1538768a0 100644 (file)
@@ -19,10 +19,9 @@ import com.google.common.collect.Lists
 import java.beans.ConstructorProperties
 import java.util.ArrayList
 import java.util.Base64;
-import java.util.Collections
+import java.util.Comparator
 import java.util.List
 import java.util.Map
-import java.util.regex.Pattern
 import javax.management.ConstructorParameters
 import org.gaul.modernizer_maven_annotations.SuppressModernizer
 import org.opendaylight.mdsal.binding.model.api.ConcreteType
@@ -33,7 +32,6 @@ import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.mdsal.binding.model.api.Restrictions
 import org.opendaylight.mdsal.binding.model.api.Type
 import org.opendaylight.mdsal.binding.model.util.TypeConstants
-import org.opendaylight.yangtools.yang.binding.CodeHelpers
 import org.opendaylight.yangtools.yang.common.Empty
 import org.opendaylight.yangtools.yang.common.Uint16
 import org.opendaylight.yangtools.yang.common.Uint32
@@ -46,11 +44,12 @@ import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
  */
 @SuppressModernizer
 class ClassTemplate extends BaseTemplate {
+    static val Comparator<GeneratedProperty> PROP_COMPARATOR = Comparator.comparing([prop | prop.name])
 
     protected val List<GeneratedProperty> properties
     protected val List<GeneratedProperty> finalProperties
     protected val List<GeneratedProperty> parentProperties
-    protected val Iterable<GeneratedProperty> allProperties
+    protected val List<GeneratedProperty> allProperties
     protected val Restrictions restrictions
 
     /**
@@ -89,12 +88,10 @@ class ClassTemplate extends BaseTemplate {
         this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)
         this.restrictions = genType.restrictions
 
-        var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();
+        val sorted = new ArrayList();
         sorted.addAll(properties);
         sorted.addAll(parentProperties);
-        Collections.sort(sorted, [p1, p2|
-            p1.name.compareTo(p2.name)
-        ]);
+        sorted.sort(PROP_COMPARATOR);
 
         this.allProperties = sorted
         this.enums = genType.enumerations
@@ -202,9 +199,14 @@ class ClassTemplate extends BaseTemplate {
     def protected constructors() '''
         «IF genTO.unionType»
             «genUnionConstructor»
+        «ELSEIF genTO.typedef && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+            «typedefConstructor»
+            «legacyConstructor»
         «ELSE»
             «allValuesConstructor»
+            «legacyConstructor»
         «ENDIF»
+
         «IF !allProperties.empty»
             «copyConstructor»
         «ENDIF»
@@ -213,44 +215,77 @@ class ClassTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
-    def protected allValuesConstructor() '''
-    «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
-        @«ConstructorParameters.importedName»("value")
-        @«ConstructorProperties.importedName»("value")
-    «ENDIF»
+    def private allValuesConstructor() '''
     public «type.name»(«allProperties.asArgumentsDeclaration») {
         «IF false == parentProperties.empty»
             super(«parentProperties.asArguments»);
         «ENDIF»
         «FOR p : allProperties»
-            «generateRestrictions(type, p.fieldName.toString, p.returnType)»
+            «generateRestrictions(type, p.fieldName, 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")»
-            «CodeHelpers.importedName».requireValue(_value);
-            «genPatternEnforcer("_value")»
+        «FOR p : properties»
+            «val fieldName = p.fieldName»
+            «IF p.returnType.name.endsWith("[]")»
+                this.«fieldName» = «fieldName» == null ? null : «fieldName».clone();
+            «ELSE»
+                this.«fieldName» = «fieldName»;
+            «ENDIF»
+        «ENDFOR»
+    }
+    '''
+
+    def private typedefConstructor() '''
+    @«ConstructorParameters.importedName»("value")
+    @«ConstructorProperties.importedName»("value")
+    public «type.name»(«allProperties.asArgumentsDeclaration») {
+        «IF false == parentProperties.empty»
+            super(«parentProperties.asArguments»);
         «ENDIF»
+        «FOR p : allProperties»
+            «generateRestrictions(type, p.fieldName, 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.
+         */»
+        «CODEHELPERS.importedName».requireValue(_value);
+        «genPatternEnforcer("_value")»
 
         «FOR p : properties»
-            «IF p.returnType.importedName.contains("[]")»
-                «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name
-                .equals("value")»
-                this.«p.fieldName» = «p.fieldName».clone();
-                «ELSE»
-                this.«p.fieldName» = «p.fieldName» == null ? null : «p.fieldName».clone();
-                «ENDIF»
+            «val fieldName = p.fieldName»
+            «IF p.returnType.name.endsWith("[]")»
+                this.«fieldName» = «fieldName».clone();
             «ELSE»
-            this.«p.fieldName» = «p.fieldName»;
+                this.«fieldName» = «fieldName»;
             «ENDIF»
         «ENDFOR»
     }
-
     '''
 
+    def private legacyConstructor() {
+        if (!hasUintProperties) {
+            return ""
+        }
+
+        val compatUint = CODEHELPERS.importedName + ".compatUint("
+        return '''
+
+            /**
+             * Utility migration constructor.
+             *
+             «FOR prop : allProperties»
+             * @param «prop.fieldName» «prop.name»«IF prop.isUintType» in legacy Java type«ENDIF»
+             «ENDFOR»
+             * @deprecated Use {#link «type.name»(«FOR prop : allProperties SEPARATOR ", "»«prop.returnType.importedJavadocName»«ENDFOR»)} instead.
+             */
+            @Deprecated(forRemoval = true)
+            public «type.getName»(«FOR prop : allProperties SEPARATOR ", "»«prop.legacyType.importedName» «prop.fieldName»«ENDFOR») {
+                this(«FOR prop : allProperties SEPARATOR ", "»«IF prop.isUintType»«compatUint»«prop.fieldName»)«ELSE»«prop.fieldName»«ENDIF»«ENDFOR»);
+            }
+        '''
+    }
+
     def protected genUnionConstructor() '''
     «FOR p : allProperties»
         «val List<GeneratedProperty> other = new ArrayList(properties)»
@@ -258,18 +293,18 @@ class ClassTemplate extends BaseTemplate {
             «genConstructor(p, other)»
         «ENDIF»
     «ENDFOR»
-
     '''
 
-    def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''
+    def protected genConstructor(GeneratedProperty property, Iterable<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)»
+        «val fieldName = property.fieldName»
+        «generateRestrictions(type, fieldName, property.returnType)»
 
-        this.«property.fieldName» = «property.name»;
+        this.«fieldName» = «property.name»;
         «FOR p : other»
             this.«p.fieldName» = null;
         «ENDFOR»
@@ -279,7 +314,7 @@ class ClassTemplate extends BaseTemplate {
     def private genPatternEnforcer(String ref) '''
         «FOR c : consts»
             «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
-            «CodeHelpers.importedName».checkPattern(«ref», «Constants.MEMBER_PATTERN_LIST», «Constants.MEMBER_REGEX_LIST»);
+            «CODEHELPERS.importedName».checkPattern(«ref», «Constants.MEMBER_PATTERN_LIST», «Constants.MEMBER_REGEX_LIST»);
             «ENDIF»
         «ENDFOR»
     '''
@@ -319,7 +354,8 @@ class ClassTemplate extends BaseTemplate {
             super(source);
         «ENDIF»
         «FOR p : properties»
-            this.«p.fieldName» = source.«p.fieldName»;
+            «val fieldName = p.fieldName»
+            this.«fieldName» = source.«fieldName»;
         «ENDFOR»
     }
     '''
@@ -377,7 +413,7 @@ class ClassTemplate extends BaseTemplate {
     '''
 
     def protected bitsArgs() '''
-        «List.importedName»<«String.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
+        «JU_LIST.importedName»<«STRING.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
         if (!properties.contains(defaultValue)) {
             throw new «IllegalArgumentException.importedName»("invalid default parameter");
         }
@@ -458,13 +494,14 @@ class ClassTemplate extends BaseTemplate {
             «FOR c : consts»
                 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
                     «val cValue = c.value as Map<String, String>»
-                    public static final «List.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «ImmutableList.importedName».of(«
+                    «val jurPatternRef = JUR_PATTERN.importedName»
+                    public static final «JU_LIST.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «ImmutableList.importedName».of(«
                     FOR v : cValue.keySet SEPARATOR ", "»"«v.escapeJava»"«ENDFOR»);
                     «IF cValue.size == 1»
-                        private static final «Pattern.importedName» «Constants.MEMBER_PATTERN_LIST» = «Pattern.importedName».compile(«TypeConstants.PATTERN_CONSTANT_NAME».get(0));
-                        private static final String «Constants.MEMBER_REGEX_LIST» = "«cValue.values.get(0).escapeJava»";
+                        private static final «jurPatternRef» «Constants.MEMBER_PATTERN_LIST» = «jurPatternRef».compile(«TypeConstants.PATTERN_CONSTANT_NAME».get(0));
+                        private static final String «Constants.MEMBER_REGEX_LIST» = "«cValue.values.iterator.next.escapeJava»";
                     «ELSE»
-                        private static final «Pattern.importedName»[] «Constants.MEMBER_PATTERN_LIST» = «CodeHelpers.importedName».compilePatterns(«TypeConstants.PATTERN_CONSTANT_NAME»);
+                        private static final «jurPatternRef»[] «Constants.MEMBER_PATTERN_LIST» = «CODEHELPERS.importedName».compilePatterns(«TypeConstants.PATTERN_CONSTANT_NAME»);
                         private static final String[] «Constants.MEMBER_REGEX_LIST» = { «
                         FOR v : cValue.values SEPARATOR ", "»"«v.escapeJava»"«ENDFOR» };
                     «ENDIF»
@@ -503,13 +540,13 @@ class ClassTemplate extends BaseTemplate {
             return ""
         }
         return '''
-            @«Override.importedName»
+            @«OVERRIDE.importedName»
             public int hashCode() {
                 «IF size != 1»
                     «hashCodeResult(genTO.hashCodeIdentifiers)»
                     return result;
                 «ELSE»
-                    return «CodeHelpers.importedName».wrapperHashCode(«genTO.hashCodeIdentifiers.get(0).fieldName»);
+                    return «CODEHELPERS.importedName».wrapperHashCode(«genTO.hashCodeIdentifiers.get(0).fieldName»);
                 «ENDIF»
             }
         '''
@@ -522,7 +559,7 @@ class ClassTemplate extends BaseTemplate {
      */
     def private generateEquals() '''
         «IF !genTO.equalsIdentifiers.empty»
-            @«Override.importedName»
+            @«OVERRIDE.importedName»
             public final boolean equals(java.lang.Object obj) {
                 if (this == obj) {
                     return true;
@@ -548,7 +585,28 @@ class ClassTemplate extends BaseTemplate {
                 return prop;
             }
         }
-        return null;
+        return null
     }
 
+    def private hasUintProperties() {
+        for (GeneratedProperty prop : allProperties) {
+            if (prop.isUintType) {
+                return true
+            }
+        }
+        return false
+    }
+
+    def private static isUintType(GeneratedProperty prop) {
+        UINT_TYPES.containsKey(prop.returnType)
+    }
+
+    def private static legacyType(GeneratedProperty prop) {
+        val type = prop.returnType
+        val uint = UINT_TYPES.get(type)
+        if (uint !== null) {
+            return uint
+        }
+        return type
+    }
 }