BUG-1119: optimize length and range checks in generated sources. 92/7892/9
authorMartin Vitez <mvitez@cisco.com>
Tue, 10 Jun 2014 13:40:43 +0000 (15:40 +0200)
committerMartin Vitez <mvitez@cisco.com>
Wed, 2 Jul 2014 07:50:59 +0000 (09:50 +0200)
Constraints are generated only once (by double-checked locking) and stored as immutable static variable.
BigInteger and BigDecimal values 0, 1 and 10 are represented as Big*.ZERO, ONE or TEN.
BigInteger values are created via BigInteger.valueOf(long) call.

Change-Id: Idb54d841fe64fd5a32af38b30126a314d6bc7a0d
Signed-off-by: Martin Vitez <mvitez@cisco.com>
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/ParserListenerUtils.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/TypesResolutionTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserWithContextTest.java

index ababc45775c1109d26845bd472cd22adb951b411..672d4b648e94eea593dbd1d04a8d6415bcefa751 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.yangtools.binding.generator.util.Types
 import com.google.common.base.Splitter
 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
 import com.google.common.collect.Range
-import java.util.ArrayList
 import java.util.List
 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
@@ -23,9 +22,11 @@ import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
 import java.util.Collection
 import java.util.Arrays
 import java.util.HashMap
+import com.google.common.collect.ImmutableList
+import java.math.BigInteger
+import java.math.BigDecimal
 
 abstract class BaseTemplate {
-
     protected val GeneratedType type;
     protected val Map<String, String> importMap;
     static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
@@ -170,93 +171,79 @@ abstract class BaseTemplate {
     }
 
     def generateRestrictions(Type type, String paramName, Type returnType) '''
-        «val boolean isArray = returnType.name.contains("[")»
-        «processRestrictions(type, paramName, returnType, isArray)»
-    '''
-
-    def generateRestrictions(GeneratedProperty field, String paramName) '''
-        «val Type type = field.returnType»
-        «IF type instanceof ConcreteType»
-            «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
-        «ELSEIF type instanceof GeneratedTransferObject»
-            «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
-        «ENDIF»
-    '''
-
-
-    private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
         «val restrictions = type.getRestrictions»
         «IF restrictions !== null»
+            «val boolean isNestedType = !(returnType instanceof ConcreteType)»
             «IF !restrictions.lengthConstraints.empty»
-                «generateLengthRestriction(type, restrictions, paramName, isArray,
-            !(returnType instanceof ConcreteType))»
+                «generateLengthRestriction(returnType, restrictions, paramName, isNestedType)»
             «ENDIF»
-            «IF !restrictions.rangeConstraints.empty &&
-            ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
-                «generateRangeRestriction(type, returnType, restrictions, paramName,
-            !(returnType instanceof ConcreteType))»
+            «IF !restrictions.rangeConstraints.empty»
+                «generateRangeRestriction(returnType, restrictions, paramName, isNestedType)»
             «ENDIF»
         «ENDIF»
     '''
 
-    def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
-        boolean isNestedType) '''
+    def private generateLengthRestriction(Type returnType, Restrictions restrictions, String paramName, boolean isNestedType) '''
+        «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
         if («paramName» != null) {
+            «printLengthConstraint(returnType, clazz, paramName, isNestedType, returnType.name.contains("["))»
             boolean isValidLength = false;
-            «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
-            importedName»<>(); 
-            «FOR r : restrictions.lengthConstraints»
-                lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
-            «ENDFOR»
-            for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
-                «IF isArray»
-                    «IF isNestedType»
-                        if (r.contains(«paramName».getValue().length)) {
-                    «ELSE»
-                        if (r.contains(«paramName».length)) {
-                    «ENDIF»
-                «ELSE»
-                    «IF isNestedType»
-                        if (r.contains(«paramName».getValue().length())) {
-                    «ELSE»
-                        if (r.contains(«paramName».length())) {
-                    «ENDIF»
-                «ENDIF»
-                isValidLength = true;
+            for («Range.importedName»<«clazz.importedNumber»> r : «IF isNestedType»«returnType.importedName».«ENDIF»length()) {
+                if (r.contains(_constraint)) {
+                    isValidLength = true;
                 }
             }
             if (!isValidLength) {
-                throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», lengthConstraints));
+                throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», «IF isNestedType»«returnType.importedName».«ENDIF»length()));
             }
         }
     '''
 
-    def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
-        boolean isNestedType) '''
-        «val javaType = Class.forName(returnType.fullyQualifiedName)»
+    def private generateRangeRestriction(Type returnType, Restrictions restrictions, String paramName, boolean isNestedType) '''
+        «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
         if («paramName» != null) {
+            «printRangeConstraint(returnType, clazz, paramName, isNestedType)»
             boolean isValidRange = false;
-            «List.importedName»<«Range.importedName»<«javaType.importedName»>> rangeConstraints = new «ArrayList.
-            importedName»<>(); 
-            «FOR r : restrictions.rangeConstraints»
-                rangeConstraints.add(«Range.importedName».closed(new «javaType.importedName»(«r.min.toQuote»), new «javaType.
-            importedName»(«r.max.toQuote»)));
-            «ENDFOR»
-            for («Range.importedName»<«javaType.importedName»> r : rangeConstraints) {
-                «IF isNestedType»
-                    if (r.contains(«paramName».getValue())) {
-                «ELSE»
-                    if (r.contains(«paramName»)) {
-                «ENDIF»
-                isValidRange = true;
+            for («Range.importedName»<«clazz.importedNumber»> r : «IF isNestedType»«returnType.importedName».«ENDIF»range()) {
+                if (r.contains(_constraint)) {
+                    isValidRange = true;
                 }
             }
             if (!isValidRange) {
-                throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», rangeConstraints));
+                throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», «IF isNestedType»«returnType.importedName».«ENDIF»range()));
             }
         }
     '''
 
+    /**
+     * Print length constraint.
+     * This should always be a BigInteger (only string and binary can have length restriction)
+     */
+    def printLengthConstraint(Type returnType, Class<? extends Number> clazz, String paramName, boolean isNestedType, boolean isArray) '''
+        «clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName»«IF isNestedType».getValue()«ENDIF».length«IF !isArray»()«ENDIF»);
+    '''
+
+    def printRangeConstraint(Type returnType, Class<? extends Number> clazz, String paramName, boolean isNestedType) '''
+        «IF clazz.canonicalName.equals(BigDecimal.canonicalName)»
+            «clazz.importedNumber» _constraint = new «clazz.importedNumber»(«paramName»«IF isNestedType».getValue()«ENDIF».toString());
+        «ELSE»
+            «IF isNestedType»
+                «val propReturnType = findProperty(returnType as GeneratedTransferObject, "value").returnType»
+                «IF propReturnType.fullyQualifiedName.equals(BigInteger.canonicalName)»
+                    «clazz.importedNumber» _constraint = «paramName».getValue();
+                «ELSE»
+                    «clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName».getValue());
+                «ENDIF»
+            «ELSE»
+                «IF returnType.fullyQualifiedName.equals(BigInteger.canonicalName)»
+                    «clazz.importedNumber» _constraint = «paramName»;
+                «ELSE»
+                    «clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName»);
+                «ENDIF»
+            «ENDIF»
+        «ENDIF»
+    '''
+
     def protected generateToString(Collection<GeneratedProperty> properties) '''
         «IF !properties.empty»
             @Override
@@ -305,24 +292,13 @@ abstract class BaseTemplate {
 
     def boolean isArrayType(GeneratedTransferObject type) {
         var isArray = false
-        val GeneratedTransferObject superType = type.findSuperType
-        val GeneratedProperty value = superType.getPropByName("value")
+        val GeneratedProperty value = findProperty(type, "value")
         if (value != null && value.returnType.name.contains("[")) {
             isArray = true
         }
         return isArray
     }
 
-    def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
-        var GeneratedTransferObject base = gto
-        var GeneratedTransferObject superType = base.superType
-        while (superType !== null) {
-            base = superType
-            superType = base.superType
-        }
-        return base;
-    }
-
     def String toQuote(Object obj) {
         return "\"" + obj.toString + "\"";
     }
@@ -342,4 +318,111 @@ abstract class BaseTemplate {
         ENDIF
     »'''
 
+    def protected generateLengthMethod(String methodName, Type type, String className, String varName) '''
+        «val Restrictions restrictions = type.restrictions»
+        «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
+            «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
+            public static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> «methodName»() {
+                «IF numberClass.equals(typeof(BigDecimal))»
+                    «lengthMethodBody(restrictions, numberClass, className, varName)»
+                «ELSE»
+                    «lengthMethodBody(restrictions, typeof(BigInteger), className, varName)»
+                «ENDIF»
+            }
+        «ENDIF»
+    '''
+
+    def private lengthMethodBody(Restrictions restrictions, Class<? extends Number> numberClass, String className, String varName) '''
+        if («varName» == null) {
+            synchronized («className».class) {
+                if («varName» == null) {
+                    «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();
+                }
+            }
+        }
+        return «varName»;
+    '''
+
+    def protected generateRangeMethod(String methodName, Type type, String className, String varName) '''
+        «val Restrictions restrictions = type.restrictions»
+        «IF restrictions != null && !(restrictions.rangeConstraints.empty)»
+            «val numberClass = restrictions.rangeConstraints.iterator.next.min.class»
+            public static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> «methodName»() {
+                «IF numberClass.equals(typeof(BigDecimal))»
+                    «rangeMethodBody(restrictions, numberClass, className, varName)»
+                «ELSE»
+                    «rangeMethodBody(restrictions, typeof(BigInteger), className, varName)»
+                «ENDIF»
+            }
+        «ENDIF»
+    '''
+
+    def private rangeMethodBody(Restrictions restrictions, Class<? extends Number> numberClass, String className, String varName) '''
+        if («varName» == null) {
+            synchronized («className».class) {
+                if («varName» == null) {
+                    «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();
+                }
+            }
+        }
+        return «varName»;
+    '''
+
+    def protected String importedNumber(Class<? extends Number> clazz) {
+        if (clazz.equals(typeof(BigDecimal))) {
+            return BigDecimal.importedName
+        }
+        return BigInteger.importedName
+    }
+
+    def private String numericValue(Class<? extends Number> clazz, Object numberValue) {
+        val number = clazz.importedName;
+        val value = numberValue.toString
+        if (clazz.equals(typeof(BigInteger)) || clazz.equals(typeof(BigDecimal))) {
+            if (value.equals("0")) {
+                return number + ".ZERO"
+            } else if (value.equals("1")) {
+                return number + ".ONE"
+            } else if (value.equals("10")) {
+                return number + ".TEN"
+            } else {
+                try {
+                    val Long longVal = Long.valueOf(value)
+                    return number + ".valueOf(" + longVal + "L)"
+                } catch (NumberFormatException e) {
+                    if (clazz.equals(typeof(BigDecimal))) {
+                        try {
+                            val Double doubleVal = Double.valueOf(value);
+                            return number + ".valueOf(" + doubleVal + ")"
+                        } catch (NumberFormatException e2) {
+                        }
+                    }
+                }
+            }
+        }
+        return "new " + number + "(\"" + value + "\")"
+    }
+
+    def private GeneratedProperty findProperty(GeneratedTransferObject gto, String name) {
+        val props = gto.properties
+        for (prop : props) {
+            if (prop.name.equals(name)) {
+                return prop
+            }
+        }
+        val GeneratedTransferObject parent = gto.superType
+        if (parent != null) {
+            return findProperty(parent, name)
+        }
+        return null
+    }
+
 }
index 7dd355230387a27ca245954b12a8ab9dd826e705..fbd198054a40310ecd6300ec79aa6e4c8af7f258 100644 (file)
@@ -29,6 +29,8 @@ import java.util.ArrayList
 import java.util.HashSet
 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
 
 /**
  * Template for generating JAVA builder classes. 
@@ -154,7 +156,7 @@ class BuilderTemplate extends BaseTemplate {
      * @param set of method signature instances which should be transformed to list of properties 
      * @return set of generated property instances which represents the getter <code>methods</code>
      */
-    def private propertiesFromMethods(Set<MethodSignature> methods) {
+    def private propertiesFromMethods(Collection<MethodSignature> methods) {
         if (methods == null || methods.isEmpty()) {
             return Collections.emptySet
         }
@@ -390,16 +392,27 @@ class BuilderTemplate extends BaseTemplate {
         return names
     }
 
-       /**
-        * Template method which generates class attributes.
-        * 
-        * @param boolean value which specify whether field is|isn't final
-        * @return string with class attributes and their types
-        */
+    /**
+     * Template method which generates class attributes.
+     *
+     * @param boolean value which specify whether field is|isn't final
+     * @return string with class attributes and their types
+     */
     def private generateFields(boolean _final) '''
-        «IF !properties.empty»
+        «IF properties !== null»
             «FOR f : properties»
                 private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
+                «val restrictions = f.returnType.restrictions»
+                «IF !_final && restrictions != null»
+                    «IF !(restrictions.lengthConstraints.empty)»
+                        «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
+                        private static «List.importedName»<«Range.importedName»<«clazz.importedNumber»>> «f.fieldName»_length;
+                    «ENDIF»
+                    «IF !(restrictions.rangeConstraints.empty)»
+                        «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
+                        private static «List.importedName»<«Range.importedName»<«clazz.importedNumber»>> «f.fieldName»_range;
+                    «ENDIF»
+                «ENDIF»
             «ENDFOR»
         «ENDIF»
     '''
@@ -410,19 +423,22 @@ class BuilderTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
-       /**
-        * Template method which generates setter methods
-        * 
-        * @return string with the setter methods 
-        */
+    /**
+     * Template method which generates setter methods
+     *
+     * @return string with the setter methods
+     */
     def private generateSetters() '''
         «FOR field : properties SEPARATOR '\n'»
+            «val length = field.fieldName + "_length"»
+            «val range = field.fieldName + "_range"»
             public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {
-                «generateRestrictions(field, "value")»
-
+                «generateRestrictions(field, "value", length, range)»
                 this.«field.fieldName» = value;
                 return this;
             }
+            «generateLengthMethod(length, field.returnType, type.name+BUILDER, length)»
+            «generateRangeMethod(range, field.returnType, type.name+BUILDER, range)»
         «ENDFOR»
         «IF augmentField != null»
 
@@ -433,6 +449,62 @@ class BuilderTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
+    def generateRestrictions(GeneratedProperty field, String paramName, String lengthGetter, String rangeGetter) '''
+        «val Type type = field.returnType»
+        «IF type instanceof ConcreteType»
+            «createRestrictions(type, paramName, type.name.contains("["), lengthGetter, rangeGetter)»
+        «ELSEIF type instanceof GeneratedTransferObject»
+            «createRestrictions(type, paramName, isArrayType(type as GeneratedTransferObject), lengthGetter, rangeGetter)»
+        «ENDIF»
+    '''
+
+    def private createRestrictions(Type type, String paramName, boolean isArray, String lengthGetter, String rangeGetter) '''
+        «val restrictions = type.getRestrictions»
+        «IF restrictions !== null»
+            «val boolean isNestedType = !(type instanceof ConcreteType)»
+            «IF !restrictions.lengthConstraints.empty»
+                «generateLengthRestriction(type, paramName, lengthGetter, isNestedType, isArray)»
+            «ENDIF»
+            «IF !restrictions.rangeConstraints.empty»
+                «generateRangeRestriction(type, paramName, rangeGetter, isNestedType, isArray)»
+            «ENDIF»
+        «ENDIF»
+    '''
+
+    def private generateLengthRestriction(Type type, String paramName, String getterName, boolean isNestedType, boolean isArray) '''
+        «val restrictions = type.getRestrictions»
+        if («paramName» != null) {
+            «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
+            «printLengthConstraint(type, clazz, paramName, isNestedType, isArray)»
+            boolean isValidLength = false;
+            for («Range.importedName»<«clazz.importedNumber»> r : «getterName»()) {
+                if (r.contains(_constraint)) {
+                    isValidLength = true;
+                }
+            }
+            if (!isValidLength) {
+                throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», «getterName»));
+            }
+        }
+    '''
+
+    def private generateRangeRestriction(Type type, String paramName, String getterName, boolean isNestedType, boolean isArray) '''
+        «val restrictions = type.getRestrictions»
+        if («paramName» != null) {
+            «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
+            «printRangeConstraint(type, clazz, paramName, isNestedType)»
+            boolean isValidRange = false;
+            for («Range.importedName»<«clazz.importedNumber»> r : «getterName»()) {
+                if (r.contains(_constraint)) {
+                    isValidRange = true;
+                }
+            }
+            if (!isValidRange) {
+                throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», «getterName»));
+            }
+        }
+    '''
+
     /**
      * Template method which generate constructor for IMPL class.
      * 
index fd033e4c74ade1dd93512759a0ed3740aef76c97..85b2df5d6243ad2f765ffae0943d1e91a8203f9e 100644 (file)
@@ -125,9 +125,9 @@ class ClassTemplate extends BaseTemplate {
 
             «generateToString(genTO.toStringIdentifiers)»
 
-            «generateGetLength»
+            «generateLengthMethod("length", genTO, genTO.importedName, "_length")»
 
-            «generateGetRange»
+            «generateRangeMethod("range", genTO, genTO.importedName, "_range")»
 
         }
     '''
@@ -164,7 +164,7 @@ class ClassTemplate extends BaseTemplate {
             «parentConstructor»
         «ENDIF»
     '''
-    
+
     def protected allValuesConstructor() '''
     «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
         @«ConstructorProperties.importedName»("value")
@@ -365,6 +365,16 @@ class ClassTemplate extends BaseTemplate {
      * @return string with the class attributes in JAVA format
      */
     def protected generateFields() '''
+        «IF restrictions != null»
+            «IF !(restrictions.lengthConstraints.empty)»
+                «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
+                private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _length;
+            «ENDIF»
+            «IF !(restrictions.rangeConstraints.empty)»
+                «val numberClass = restrictions.rangeConstraints.iterator.next.min.class»
+                private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _range;
+            «ENDIF»
+        «ENDIF»
         «IF !properties.empty»
             «FOR f : properties»
                 «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»;
@@ -434,30 +444,4 @@ class ClassTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
-    def private generateGetLength() '''
-        «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
-            «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
-            public static «List.importedName»<«Range.importedName»<«clazz.importedName»>> length() {
-                final «List.importedName»<«Range.importedName»<«clazz.importedName»>> result = new «ArrayList.importedName»<>();
-                «FOR r : restrictions.lengthConstraints»
-                    result.add(«Range.importedName».closed(new «clazz.importedName»("«r.min»"), new «clazz.importedName»("«r.max»")));
-                «ENDFOR»
-                return result;
-            }
-        «ENDIF»
-    '''
-
-    def private generateGetRange() '''
-        «IF restrictions != null && !(restrictions.rangeConstraints.empty)»
-            «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
-            public static «List.importedName»<«Range.importedName»<«clazz.importedName»>> range() {
-                final «List.importedName»<«Range.importedName»<«clazz.importedName»>> result = new «ArrayList.importedName»<>();
-                «FOR r : restrictions.rangeConstraints»
-                    result.add(«Range.importedName».closed(new «clazz.importedName»("«r.min»"), new «clazz.importedName»("«r.max»")));
-                «ENDFOR»
-                return result;
-            }
-        «ENDIF»
-    '''
-
 }
index 1af8d64ecedb05dd82169c72403f0ea97d89322a..f8b2eda1a662f0831e56393b2011b7cc9cd14e35 100644 (file)
@@ -50,6 +50,8 @@ public class TypedefCompilationTest extends BaseCompilationTest {
     private static final String VAL = "_value";
     private static final String GET_VAL = "getValue";
     private static final String UNITS = "_UNITS";
+    private static final String LENGTH = "_length";
+    private static final String RANGE = "_range";
 
     @Test
     public void test() throws Exception {
@@ -134,8 +136,9 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         // typedef int32-ext1
         assertFalse(int32Ext1Class.isInterface());
         assertContainsField(int32Ext1Class, VAL, Integer.class);
+        assertContainsField(int32Ext1Class, RANGE, List.class);
         assertContainsFieldWithValue(int32Ext1Class, "serialVersionUID", Long.TYPE, 5351634010010233292L, Integer.class);
-        assertEquals(2, int32Ext1Class.getDeclaredFields().length);
+        assertEquals(3, int32Ext1Class.getDeclaredFields().length);
         expectedConstructor = assertContainsConstructor(int32Ext1Class, Integer.class);
         assertContainsConstructor(int32Ext1Class, int32Ext1Class);
         assertEquals(2, int32Ext1Class.getConstructors().length);
@@ -155,9 +158,10 @@ public class TypedefCompilationTest extends BaseCompilationTest {
 
         // typedef int32-ext2
         assertFalse(int32Ext2Class.isInterface());
+        assertContainsField(int32Ext1Class, RANGE, List.class);
         assertContainsFieldWithValue(int32Ext2Class, UNITS, String.class, "mile", Integer.class);
         assertContainsFieldWithValue(int32Ext2Class, "serialVersionUID", Long.TYPE, 317831889060130988L, Integer.class);
-        assertEquals(2, int32Ext2Class.getDeclaredFields().length);
+        assertEquals(3, int32Ext2Class.getDeclaredFields().length);
         expectedConstructor = assertContainsConstructor(int32Ext2Class, Integer.class);
         assertContainsConstructor(int32Ext2Class, int32Ext2Class);
         assertContainsConstructor(int32Ext2Class, int32Ext1Class);
@@ -179,10 +183,11 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         // typedef string-ext1
         assertFalse(stringExt1Class.isInterface());
         assertContainsField(stringExt1Class, VAL, String.class);
+        assertContainsField(stringExt1Class, LENGTH, List.class);
         assertContainsField(stringExt1Class, "patterns", List.class);
         assertContainsField(stringExt1Class, "PATTERN_CONSTANTS", List.class);
         assertContainsFieldWithValue(stringExt1Class, "serialVersionUID", Long.TYPE, 6943827552297110991L, String.class);
-        assertEquals(4, stringExt1Class.getDeclaredFields().length);
+        assertEquals(5, stringExt1Class.getDeclaredFields().length);
         expectedConstructor = assertContainsConstructor(stringExt1Class, String.class);
         assertContainsConstructor(stringExt1Class, stringExt1Class);
         assertEquals(2, stringExt1Class.getDeclaredConstructors().length);
@@ -202,8 +207,9 @@ public class TypedefCompilationTest extends BaseCompilationTest {
 
         // typedef string-ext2
         assertFalse(stringExt2Class.isInterface());
+        assertContainsField(stringExt2Class, LENGTH, List.class);
         assertContainsFieldWithValue(stringExt2Class, "serialVersionUID", Long.TYPE, 8100233177432072092L, String.class);
-        assertEquals(1, stringExt2Class.getDeclaredFields().length);
+        assertEquals(2, stringExt2Class.getDeclaredFields().length);
         expectedConstructor = assertContainsConstructor(stringExt2Class, String.class);
         assertContainsConstructor(stringExt2Class, stringExt2Class);
         assertContainsConstructor(stringExt2Class, stringExt1Class);
@@ -237,8 +243,9 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         // typedef my-decimal-type
         assertFalse(myDecimalTypeClass.isInterface());
         assertContainsField(myDecimalTypeClass, VAL, BigDecimal.class);
+        assertContainsField(myDecimalTypeClass, RANGE, List.class);
         assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L, BigDecimal.class);
-        assertEquals(2, myDecimalTypeClass.getDeclaredFields().length);
+        assertEquals(3, myDecimalTypeClass.getDeclaredFields().length);
         assertContainsMethod(myDecimalTypeClass, BigDecimal.class, "getValue");
         expectedConstructor = assertContainsConstructor(myDecimalTypeClass, BigDecimal.class);
         assertContainsConstructor(myDecimalTypeClass, myDecimalTypeClass);
index 47b8ce1ca8d59787107914408b31749692640d89..8228d87ddcccd8d773f725a7c5a103d218d754ad 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
 import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
 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.Restrictions;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
@@ -197,15 +198,25 @@ public final class TypeProviderImpl implements TypeProvider {
             final Restrictions r) {
         Type returnType = null;
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
-        if (typeDefinition.getQName() == null) {
-            throw new IllegalArgumentException(
-                    "Type Definition cannot have non specified QName (QName cannot be NULL!)");
-        }
-        Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
+        Preconditions.checkArgument(typeDefinition.getQName() != null,
+                "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        String typedefName = typeDefinition.getQName().getLocalName();
+        Preconditions.checkArgument(typedefName != null,
                 "Type Definitions Local Name cannot be NULL!");
 
         if (typeDefinition instanceof ExtendedType) {
             returnType = javaTypeForExtendedType(typeDefinition);
+            if (r != null && returnType instanceof GeneratedTransferObject) {
+                GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
+                Module module = findParentModule(schemaContext, parentNode);
+                String basePackageName = moduleNamespaceToPackageName(module);
+                String packageName = packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
+                String genTOName = BindingMapping.getClassName(typedefName);
+                String name = packageName + "." + genTOName;
+                if (!(returnType.getFullyQualifiedName().equals(name))) {
+                    returnType = shadedTOWithRestrictions(gto, r);
+                }
+            }
         } else {
             returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
             if (returnType == null) {
@@ -222,6 +233,25 @@ public final class TypeProviderImpl implements TypeProvider {
         return returnType;
     }
 
+    private GeneratedTransferObject shadedTOWithRestrictions(GeneratedTransferObject gto, Restrictions r) {
+        GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
+        GeneratedTransferObject parent = gto.getSuperType();
+        if (parent != null) {
+            gtob.setExtendsType(parent);
+        }
+        gtob.setRestrictions(r);
+        for (GeneratedProperty gp : gto.getProperties()) {
+            GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
+            gpb.setValue(gp.getValue());
+            gpb.setReadOnly(gp.isReadOnly());
+            gpb.setAccessModifier(gp.getAccessModifier());
+            gpb.setReturnType(gp.getReturnType());
+            gpb.setFinal(gp.isFinal());
+            gpb.setStatic(gp.isStatic());
+        }
+        return gtob.toInstance();
+    }
+
     /**
      * Returns JAVA <code>Type</code> for instances of the type
      * <code>LeafrefTypeDefinition</code> or
@@ -663,7 +693,6 @@ public final class TypeProviderImpl implements TypeProvider {
         final String moduleName = module.getName();
         final Date moduleRevision = module.getRevision();
         if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
-
             final String typedefName = typedef.getQName().getLocalName();
             final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
             if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
index 49f4178731f59221fa5660efd59a1816ba210efc..0f4d4d8e53f5e13ff33f3a3eee6aca26f572137d 100644 (file)
@@ -9,14 +9,15 @@ package org.opendaylight.yangtools.yang.parser.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Optional;
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Stack;
-
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
@@ -132,8 +133,6 @@ import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
 public final class ParserListenerUtils {
     private static final Logger LOG = LoggerFactory.getLogger(ParserListenerUtils.class);
 
@@ -707,7 +706,7 @@ public final class ParserListenerUtils {
                 if (value.contains(".")) {
                     result = new BigDecimal(value);
                 } else {
-                    result = Long.valueOf(value);
+                    result = new BigInteger(value);
                 }
             } catch (NumberFormatException e) {
                 throw new YangParseException(moduleName, line, "Unable to parse range value '" + value + "'.", e);
index 4bde6510e0a7005a7becc0177f73d666aff83233..050f62092877a093f389eb8b12dca545749c1bc6 100644 (file)
@@ -14,6 +14,7 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.math.BigInteger;
 import java.net.URI;
 import java.util.List;
 import java.util.Set;
@@ -153,8 +154,8 @@ public class TypesResolutionTest {
         List<LengthConstraint> lengths = type.getLengthConstraints();
         assertEquals(1, lengths.size());
         LengthConstraint length = type.getLengthConstraints().get(0);
-        assertEquals(1L, length.getMin());
-        assertEquals(253L, length.getMax());
+        assertEquals(BigInteger.ONE, length.getMin());
+        assertEquals(BigInteger.valueOf(253), length.getMax());
     }
 
     @Test
index ab26254433c5f249f51188c29da291e5671d1581..ae3e103c79f1fe6f7ebd7301bdfd0afc71ff6a9a 100644 (file)
@@ -18,6 +18,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.math.BigInteger;
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.ParseException;
@@ -265,8 +266,8 @@ public class YangParserTest {
         List<RangeConstraint> ranges = leafType.getRangeConstraints();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
-        assertEquals(12L, range.getMin());
-        assertEquals(20L, range.getMax());
+        assertEquals(BigInteger.valueOf(12), range.getMin());
+        assertEquals(BigInteger.valueOf(20), range.getMax());
 
         ExtendedType baseType = (ExtendedType) leafType.getBaseType();
         QName baseTypeQName = baseType.getQName();
@@ -281,11 +282,11 @@ public class YangParserTest {
         List<RangeConstraint> baseTypeRanges = baseType.getRangeConstraints();
         assertEquals(2, baseTypeRanges.size());
         RangeConstraint baseTypeRange1 = baseTypeRanges.get(0);
-        assertEquals(3L, baseTypeRange1.getMin());
-        assertEquals(9L, baseTypeRange1.getMax());
+        assertEquals(BigInteger.valueOf(3), baseTypeRange1.getMin());
+        assertEquals(BigInteger.valueOf(9), baseTypeRange1.getMax());
         RangeConstraint baseTypeRange2 = baseTypeRanges.get(1);
-        assertEquals(11L, baseTypeRange2.getMin());
-        assertEquals(20L, baseTypeRange2.getMax());
+        assertEquals(BigInteger.valueOf(11), baseTypeRange2.getMin());
+        assertEquals(BigInteger.valueOf(20), baseTypeRange2.getMax());
 
         ExtendedType base = (ExtendedType) baseType.getBaseType();
         QName baseQName = base.getQName();
@@ -300,8 +301,8 @@ public class YangParserTest {
         List<RangeConstraint> baseRanges = base.getRangeConstraints();
         assertEquals(1, baseRanges.size());
         RangeConstraint baseRange = baseRanges.get(0);
-        assertEquals(2L, baseRange.getMin());
-        assertEquals(20L, baseRange.getMax());
+        assertEquals(BigInteger.valueOf(2), baseRange.getMin());
+        assertEquals(BigInteger.valueOf(20), baseRange.getMax());
 
         assertTrue(base.getBaseType() instanceof Int32);
     }
@@ -353,8 +354,8 @@ public class YangParserTest {
         List<LengthConstraint> baseType2Lengths = baseType2.getLengthConstraints();
         assertEquals(1, baseType2Lengths.size());
         LengthConstraint length = baseType2Lengths.get(0);
-        assertEquals(6L, length.getMin());
-        assertEquals(10L, length.getMax());
+        assertEquals(BigInteger.valueOf(6), length.getMin());
+        assertEquals(BigInteger.TEN, length.getMax());
         assertTrue(baseType2.getRangeConstraints().isEmpty());
 
         ExtendedType baseType3 = (ExtendedType) baseType2.getBaseType();
@@ -372,8 +373,8 @@ public class YangParserTest {
         List<LengthConstraint> baseType3Lengths = baseType3.getLengthConstraints();
         assertEquals(1, baseType3Lengths.size());
         length = baseType3Lengths.get(0);
-        assertEquals(5L, length.getMin());
-        assertEquals(11L, length.getMax());
+        assertEquals(BigInteger.valueOf(5), length.getMin());
+        assertEquals(BigInteger.valueOf(11), length.getMax());
         assertTrue(baseType3.getRangeConstraints().isEmpty());
 
         assertTrue(baseType3.getBaseType() instanceof StringType);
@@ -397,8 +398,8 @@ public class YangParserTest {
         List<LengthConstraint> typeLengths = type.getLengthConstraints();
         assertEquals(1, typeLengths.size());
         LengthConstraint length = typeLengths.get(0);
-        assertEquals(7L, length.getMin());
-        assertEquals(10L, length.getMax());
+        assertEquals(BigInteger.valueOf(7), length.getMin());
+        assertEquals(BigInteger.TEN, length.getMax());
         assertTrue(type.getRangeConstraints().isEmpty());
 
         ExtendedType baseType1 = (ExtendedType) type.getBaseType();
@@ -413,8 +414,8 @@ public class YangParserTest {
         List<LengthConstraint> baseType2Lengths = baseType1.getLengthConstraints();
         assertEquals(1, baseType2Lengths.size());
         length = baseType2Lengths.get(0);
-        assertEquals(6L, length.getMin());
-        assertEquals(10L, length.getMax());
+        assertEquals(BigInteger.valueOf(6), length.getMin());
+        assertEquals(BigInteger.TEN, length.getMax());
         assertTrue(baseType1.getRangeConstraints().isEmpty());
 
         ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
@@ -432,8 +433,8 @@ public class YangParserTest {
         List<LengthConstraint> baseType3Lengths = baseType2.getLengthConstraints();
         assertEquals(1, baseType3Lengths.size());
         length = baseType3Lengths.get(0);
-        assertEquals(5L, length.getMin());
-        assertEquals(11L, length.getMax());
+        assertEquals(BigInteger.valueOf(5), length.getMin());
+        assertEquals(BigInteger.valueOf(11), length.getMax());
         assertTrue(baseType2.getRangeConstraints().isEmpty());
 
         assertTrue(baseType2.getBaseType() instanceof StringType);
@@ -545,8 +546,8 @@ public class YangParserTest {
         List<RangeConstraint> ranges = unionType1.getRangeConstraints();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
-        assertEquals(1L, range.getMin());
-        assertEquals(100L, range.getMax());
+        assertEquals(BigInteger.ONE, range.getMin());
+        assertEquals(BigInteger.valueOf(100), range.getMax());
         assertTrue(unionType1.getBaseType() instanceof Int16);
 
         assertTrue(unionTypes.get(1) instanceof Int32);
@@ -654,8 +655,8 @@ public class YangParserTest {
         List<RangeConstraint> ranges = int16Ext.getRangeConstraints();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
-        assertEquals(1L, range.getMin());
-        assertEquals(100L, range.getMax());
+        assertEquals(BigInteger.ONE, range.getMin());
+        assertEquals(BigInteger.valueOf(100), range.getMax());
 
         assertTrue(int16Ext.getBaseType() instanceof Int16);
     }
index 6238198b32253a52253e4d528b9aa33593a3fc20..8c4e130cbc9e54657036c25219192d1ef67c5f9a 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.collect.Lists;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
+import java.math.BigInteger;
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
@@ -85,8 +86,8 @@ public class YangParserWithContextTest {
         List<RangeConstraint> ranges = dscpExt.getRangeConstraints();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
-        assertEquals(0L, range.getMin());
-        assertEquals(63L, range.getMax());
+        assertEquals(BigInteger.ZERO, range.getMin());
+        assertEquals(BigInteger.valueOf(63), range.getMax());
     }
 
     @Test