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 6699d502006c1682cea241daa1d322b033a67d8c..f75299436645bde58056f18eaa925a2270751ef9 100644 (file)
@@ -7,6 +7,7 @@
  */
 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
@@ -20,14 +21,16 @@ 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 com.google.common.base.Preconditions
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
 
 /**
  * Template for generating JAVA class.
@@ -57,6 +60,8 @@ class ClassTemplate extends BaseTemplate {
 
     protected val GeneratedTransferObject genTO;
 
+    private val AbstractRangeGenerator<?> rangeGenerator
+
     /**
      * Creates instance of this class with concrete <code>genType</code>.
      *
@@ -81,6 +86,13 @@ class ClassTemplate extends BaseTemplate {
         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
+        }
     }
 
     /**
@@ -111,11 +123,15 @@ class ClassTemplate extends BaseTemplate {
             «constantsDeclarations»
             «generateFields»
 
-            «IF restrictions != null && (!restrictions.rangeConstraints.nullOrEmpty ||
-                !restrictions.lengthConstraints.nullOrEmpty)»
-            «generateConstraints»
-
+            «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»
@@ -137,9 +153,9 @@ class ClassTemplate extends BaseTemplate {
 
             «generateToString(genTO.toStringIdentifiers)»
 
-            «generateLengthMethod("length", "_length"
+            «generateLengthMethod()»
 
-            «generateRangeMethod("range", "_range"
+            «generateRangeMethod()»
 
         }
 
@@ -162,28 +178,47 @@ class ClassTemplate extends BaseTemplate {
         }
     '''
 
-    def private generateLengthMethod(String methodName, String varName) '''
+    @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»>> «methodName»() {
-                return «varName»;
+            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»
     '''
 
-    def private generateRangeMethod(String methodName, String varName) '''
+    @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»>> «methodName»() {
-                return «varName»;
+            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»
     '''
@@ -219,55 +254,6 @@ class ClassTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
-    def private generateConstraints() '''
-        static {
-            «IF !restrictions.rangeConstraints.nullOrEmpty»
-            «generateRangeConstraints»
-            «ENDIF»
-            «IF !restrictions.lengthConstraints.nullOrEmpty»
-            «generateLengthConstraints»
-            «ENDIF»
-        }
-    '''
-
-    private def generateRangeConstraints() '''
-        «IF !allProperties.nullOrEmpty»
-            «val returnType = allProperties.iterator.next.returnType»
-            «IF returnType.fullyQualifiedName.equals(BigDecimal.canonicalName)»
-                «rangeBody(restrictions, BigDecimal, genTO.importedName, "_range")»
-            «ELSE»
-                «rangeBody(restrictions, BigInteger, genTO.importedName, "_range")»
-            «ENDIF»
-        «ENDIF»
-    '''
-
-    private def rangeBody(Restrictions restrictions, Class<? extends Number> numberClass, String className, String varName) '''
-        «ImmutableList.importedName».Builder<«Range.importedName»<«numberClass.importedName»>> builder = «ImmutableList.importedName».builder();
-        «FOR r : restrictions.rangeConstraints»
-            builder.add(«Range.importedName».closed(«numericValue(numberClass, r.min)», «numericValue(numberClass, r.max)»));
-        «ENDFOR»
-        «varName» = builder.build();
-    '''
-
-    private def lengthBody(Restrictions restrictions, Class<? extends Number> numberClass, String className, String varName) '''
-        «ImmutableList.importedName».Builder<«Range.importedName»<«numberClass.importedName»>> builder = «ImmutableList.importedName».builder();
-        «FOR r : restrictions.lengthConstraints»
-            builder.add(«Range.importedName».closed(«numericValue(numberClass, r.min)», «numericValue(numberClass, r.max)»));
-        «ENDFOR»
-        «varName» = builder.build();
-    '''
-
-    private def generateLengthConstraints() '''
-        «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
-            «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
-            «IF numberClass.equals(typeof(BigDecimal))»
-                «lengthBody(restrictions, numberClass, genTO.importedName, "_length")»
-            «ELSE»
-                «lengthBody(restrictions, typeof(BigInteger), genTO.importedName, "_length")»
-            «ENDIF»
-        «ENDIF»
-    '''
-
     def protected allValuesConstructor() '''
     «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
         @«ConstructorProperties.importedName»("value")
@@ -290,10 +276,9 @@ class ClassTemplate extends BaseTemplate {
 
             «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 any of the permitted patterns %s", _value, «TypeConstants.PATTERN_CONSTANT_NAME»);
-            }
-
+                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»
@@ -334,6 +319,30 @@ class ClassTemplate extends BaseTemplate {
     }
     '''
 
+    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.
@@ -467,7 +476,7 @@ class ClassTemplate extends BaseTemplate {
                 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
                     «val cValue = c.value»
                     «IF cValue instanceof List<?>»
-                        private static final «List.importedName»<«Pattern.importedName»> «Constants.MEMBER_PATTERN_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»"«
@@ -491,12 +500,13 @@ class ClassTemplate extends BaseTemplate {
      */
     def protected generateStaticInicializationBlock() '''
         static {
-            final «List.importedName»<«Pattern.importedName»> l = new «ArrayList.importedName»<«Pattern.importedName»>();
+            final «Pattern.importedName» a[] = new «Pattern.importedName»[«TypeConstants.PATTERN_CONSTANT_NAME».size()];
+            int i = 0;
             for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
-                l.add(Pattern.compile(regEx));
+                a[i++] = Pattern.compile(regEx);
             }
 
-            «Constants.MEMBER_PATTERN_LIST» = «ImmutableList.importedName».copyOf(l);
+            «Constants.MEMBER_PATTERN_LIST» = a;
         }
     '''
 
@@ -506,17 +516,6 @@ class ClassTemplate extends BaseTemplate {
      * @return string with the class attributes in JAVA format
      */
     def protected generateFields() '''
-        «IF restrictions != null»
-            «val prop = getPropByName("value")»
-            «IF prop != null»
-                «IF !(restrictions.lengthConstraints.empty)»
-                    private static final «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _length;
-                «ENDIF»
-                «IF !(restrictions.rangeConstraints.empty)»
-                    private static final «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _range;
-                «ENDIF»
-            «ENDIF»
-        «ENDIF»
         «IF !properties.empty»
             «FOR f : properties»
                 private«IF f.readOnly» final«ENDIF» «f.returnType.importedName» «f.fieldName»;