Fix for Bug 134: added restriction check to classes wrapping int and uint values.
[mdsal.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / BaseTemplate.xtend
index 234361305e73d34cc357a0c74bfbaebcf9f3fd0d..f60393221088645894e66227ee46e7e8f0b63766 100644 (file)
@@ -13,38 +13,39 @@ import java.util.List
 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import java.util.Collection
 
 abstract class BaseTemplate {
-    
-    
+
     protected val GeneratedType type;
-    protected val Map<String,String> importMap;
+    protected val Map<String, String> importMap;
     static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
+
     new(GeneratedType _type) {
-         if (_type== null) {
+        if (_type == null) {
             throw new IllegalArgumentException("Generated type reference cannot be NULL!")
         }
         this.type = _type;
         this.importMap = GeneratorUtil.createImports(type)
     }
-    
-    def packageDefinition () '''package «type.packageName»;'''
 
+    def packageDefinition() '''package «type.packageName»;'''
 
     protected def getFullyQualifiedName() {
         return type.fullyQualifiedName
     }
-    
-    final public def generate() {
-    val _body = body()
-    '''
-    «packageDefinition»
-    «imports»
 
-    «_body»
-    '''.toString
+    final public def generate() {
+        val _body = body()
+        '''
+            «packageDefinition»
+            «imports»
+            
+            «_body»
+        '''.toString
     }
-    protected def imports()  ''' 
+
+    protected def imports() ''' 
         «IF !importMap.empty»
             «FOR entry : importMap.entrySet»
                 «IF entry.value != fullyQualifiedName»
@@ -52,16 +53,14 @@ abstract class BaseTemplate {
                 «ENDIF»
             «ENDFOR»
         «ENDIF»
-
+        
     '''
 
     protected abstract def CharSequence body();
 
     // Helper patterns
-
     final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
 
-
     final protected def propertyNameFromGetter(MethodSignature getter) {
         var int prefix;
         if (getter.name.startsWith("is")) {
@@ -82,18 +81,18 @@ abstract class BaseTemplate {
      * @return string with the getter method source code in JAVA format 
      */
     final protected def getterMethod(GeneratedProperty field) {
-    '''
-        public «field.returnType.importedName» «field.getterMethodName»() {
-            return «field.fieldName»;
-        }
-    '''
+        '''
+            public «field.returnType.importedName» «field.getterMethodName»() {
+                return «field.fieldName»;
+            }
+        '''
     }
 
     final protected def getterMethodName(GeneratedProperty field) {
         val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
         return '''«prefix»«field.name.toFirstUpper»'''
     }
-    
+
     /**
      * Template method which generates the setter method for <code>field</code>
      * 
@@ -108,16 +107,16 @@ abstract class BaseTemplate {
             return this;
         }
     '''
-    
+
     final protected def importedName(Type intype) {
         GeneratorUtil.putTypeIntoImports(type, intype, importMap);
         GeneratorUtil.getExplicitType(type, intype, importMap)
     }
-    
+
     final protected def importedName(Class<?> cls) {
         importedName(Types.typeForClass(cls))
     }
-    
+
     /**
      * Template method which generates method parameters with their types from <code>parameters</code>.
      * 
@@ -125,9 +124,9 @@ abstract class BaseTemplate {
      * group of generated property instances which are transformed to the method parameters
      * @return string with the list of the method parameters with their types in JAVA format
      */
-    def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) 
-    '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
-    
+    def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
+        returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
+
     /**
      * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
      * 
@@ -135,67 +134,64 @@ abstract class BaseTemplate {
      * group of generated property instances which are transformed to the sequence of parameter names
      * @return string with the list of the parameter names of the <code>parameters</code> 
      */
-    def final protected asArguments(Iterable<GeneratedProperty> parameters) 
-    '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.fieldName»«ENDFOR»«ENDIF»'''
-    
-    
-        /**
+    def final protected asArguments(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
+        fieldName»«ENDFOR»«ENDIF»'''
+
+    /**
      * Template method which generates JAVA comments.
      * 
      * @param comment string with the comment for whole JAVA class
      * @return string with comment in JAVA format
      */
     def protected CharSequence asJavadoc(String comment) {
-        if (comment==null) return '';
+        if(comment == null) return '';
         val paragraphs = paragraphSplitter.split(comment)
-        
+
         return '''
             /**
               «FOR p : paragraphs SEPARATOR "<p>"»
-              «p»
+                  «p»
               «ENDFOR»
             **/
-            '''
+        '''
     }
 
-    def generateLengthRestrictions(Type type, String paramName, Type returnType) '''
+    def generateRestrictions(Type type, String paramName, Type returnType) '''
         «val boolean isArray = returnType.name.contains("[")»
-        «IF type instanceof ConcreteType»
-            «val restrictions = (type as ConcreteType).restrictions»
-            «IF restrictions !== null && !restrictions.lengthConstraints.empty»
-                «generateLengthRestriction(type, restrictions, paramName, isArray, !(returnType instanceof ConcreteType))»
-            «ENDIF»
-        «ENDIF»
-        «IF type instanceof GeneratedTransferObject»
-            «val restrictions = (type as GeneratedTransferObject).restrictions»
-            «IF restrictions !== null && !restrictions.lengthConstraints.empty»
-                «generateLengthRestriction(type, restrictions, paramName, isArray, !(returnType instanceof ConcreteType))»
-            «ENDIF»
-        «ENDIF»
+        «processRestrictions(type, paramName, returnType, isArray)»
     '''
 
-    def generateLengthRestrictions(GeneratedProperty field, String paramName) '''
+    def generateRestrictions(GeneratedProperty field, String paramName) '''
         «val Type type = field.returnType»
         «IF type instanceof ConcreteType»
-            «val boolean isArray = type.name.contains("[")»
-            «val restrictions = (type as ConcreteType).restrictions»
-            «IF restrictions !== null && !restrictions.lengthConstraints.empty»
-                «generateLengthRestriction(type, restrictions, paramName, isArray, false)»
-            «ENDIF»
+            «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
+        «ELSEIF type instanceof GeneratedTransferObject»
+            «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
         «ENDIF»
-        «IF type instanceof GeneratedTransferObject»
-            «var isArray = isArrayType(type as GeneratedTransferObject)»
-            «val restrictions = (type as GeneratedTransferObject).restrictions»
-            «IF restrictions !== null && !restrictions.lengthConstraints.empty»
-                «generateLengthRestriction(type, restrictions, paramName, isArray, true)»
+    '''
+
+
+    private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
+        «val restrictions = type.getRestrictions»
+        «IF restrictions !== null»
+            «IF !restrictions.lengthConstraints.empty»
+                «generateLengthRestriction(type, restrictions, paramName, isArray,
+            !(returnType instanceof ConcreteType))»
+            «ENDIF»
+            «IF !restrictions.rangeConstraints.empty &&
+            ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
+                «generateRangeRestriction(type, returnType, restrictions, paramName,
+            !(returnType instanceof ConcreteType))»
             «ENDIF»
         «ENDIF»
     '''
 
-    def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray, boolean isNestedType) '''
+    def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
+        boolean isNestedType) '''
         if («paramName» != null) {
             boolean isValidLength = false;
-            «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>(); 
+            «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
+            importedName»<>(); 
             «FOR r : restrictions.lengthConstraints»
                 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
             «ENDFOR»
@@ -213,7 +209,7 @@ abstract class BaseTemplate {
                         if (r.contains(«paramName».length())) {
                     «ENDIF»
                 «ENDIF»
-                    isValidLength = true;
+                isValidLength = true;
                 }
             }
             if (!isValidLength) {
@@ -222,6 +218,32 @@ abstract class BaseTemplate {
         }
     '''
 
+    def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
+        boolean isNestedType) '''
+        «val javaType = Class.forName(returnType.fullyQualifiedName)»
+        if («paramName» != null) {
+            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;
+                }
+            }
+            if (!isValidRange) {
+                throw new IllegalArgumentException("illegal length");
+            }
+        }
+    '''
+
     def GeneratedProperty getPropByName(GeneratedType gt, String name) {
         for (GeneratedProperty prop : gt.properties) {
             if (prop.name.equals(name)) {
@@ -231,6 +253,25 @@ abstract class BaseTemplate {
         return null;
     }
 
+    def GeneratedProperty getPropByName(Collection<GeneratedProperty> props, String name) {
+        for (GeneratedProperty prop : props) {
+            if (prop.name.equals(name)) {
+                return prop;
+            }
+        }
+        return null;
+    }
+
+    def getRestrictions(Type type) {
+        var Restrictions restrictions = null
+        if (type instanceof ConcreteType) {
+            restrictions = (type as ConcreteType).restrictions
+        } else if (type instanceof GeneratedTransferObject) {
+            restrictions = (type as GeneratedTransferObject).restrictions
+        }
+        return restrictions
+    }
+
     def boolean isArrayType(GeneratedTransferObject type) {
         var isArray = false
         val GeneratedTransferObject superType = type.findSuperType
@@ -251,4 +292,8 @@ abstract class BaseTemplate {
         return base;
     }
 
+    def String toQuote(Object obj) {
+        return "\"" + obj.toString + "\"";
+    }
+
 }