Implemented length statement. Added new method to Builder classes.
[yangtools.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / BaseTemplate.xtend
1 package org.opendaylight.yangtools.sal.java.api.generator
2
3 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
4 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
5 import java.util.Map
6 import org.opendaylight.yangtools.sal.binding.model.api.Type
7 import org.opendaylight.yangtools.binding.generator.util.Types
8 import com.google.common.base.Splitter
9 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
10 import com.google.common.collect.Range
11 import java.util.ArrayList
12 import java.util.List
13 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
14 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
15 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
16
17 abstract class BaseTemplate {
18     
19     
20     protected val GeneratedType type;
21     protected val Map<String,String> importMap;
22     static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
23     new(GeneratedType _type) {
24          if (_type== null) {
25             throw new IllegalArgumentException("Generated type reference cannot be NULL!")
26         }
27         this.type = _type;
28         this.importMap = GeneratorUtil.createImports(type)
29     }
30     
31     def packageDefinition () '''package «type.packageName»;'''
32
33
34     protected def getFullyQualifiedName() {
35         return type.fullyQualifiedName
36     }
37     
38     final public def generate() {
39     val _body = body()
40     '''
41     «packageDefinition»
42     «imports»
43
44     «_body»
45     '''.toString
46     }
47     protected def imports()  ''' 
48         «IF !importMap.empty»
49             «FOR entry : importMap.entrySet»
50                 «IF entry.value != fullyQualifiedName»
51                     import «entry.value».«entry.key»;
52                 «ENDIF»
53             «ENDFOR»
54         «ENDIF»
55
56     '''
57
58     protected abstract def CharSequence body();
59
60     // Helper patterns
61
62     final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
63
64
65     final protected def propertyNameFromGetter(MethodSignature getter) {
66         var int prefix;
67         if (getter.name.startsWith("is")) {
68             prefix = 2
69         } else if (getter.name.startsWith("get")) {
70             prefix = 3
71         } else {
72             throw new IllegalArgumentException("Not a getter")
73         }
74         return getter.name.substring(prefix).toFirstLower;
75     }
76
77     /**
78      * Template method which generates the getter method for <code>field</code>
79      * 
80      * @param field 
81      * generated property with data about field which is generated as the getter method
82      * @return string with the getter method source code in JAVA format 
83      */
84     final protected def getterMethod(GeneratedProperty field) {
85     '''
86         public «field.returnType.importedName» «field.getterMethodName»() {
87             return «field.fieldName»;
88         }
89     '''
90     }
91
92     final protected def getterMethodName(GeneratedProperty field) {
93         val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
94         return '''«prefix»«field.name.toFirstUpper»'''
95     }
96     
97     /**
98      * Template method which generates the setter method for <code>field</code>
99      * 
100      * @param field 
101      * generated property with data about field which is generated as the setter method
102      * @return string with the setter method source code in JAVA format 
103      */
104     final protected def setterMethod(GeneratedProperty field) '''
105         «val returnType = field.returnType.importedName»
106         public «type.name» set«field.name.toFirstUpper»(«returnType» value) {
107             this.«field.fieldName» = value;
108             return this;
109         }
110     '''
111     
112     final protected def importedName(Type intype) {
113         GeneratorUtil.putTypeIntoImports(type, intype, importMap);
114         GeneratorUtil.getExplicitType(type, intype, importMap)
115     }
116     
117     final protected def importedName(Class<?> cls) {
118         importedName(Types.typeForClass(cls))
119     }
120     
121     /**
122      * Template method which generates method parameters with their types from <code>parameters</code>.
123      * 
124      * @param parameters
125      * group of generated property instances which are transformed to the method parameters
126      * @return string with the list of the method parameters with their types in JAVA format
127      */
128     def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) 
129     '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
130     
131     /**
132      * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
133      * 
134      * @param parameters 
135      * group of generated property instances which are transformed to the sequence of parameter names
136      * @return string with the list of the parameter names of the <code>parameters</code> 
137      */
138     def final protected asArguments(Iterable<GeneratedProperty> parameters) 
139     '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.fieldName»«ENDFOR»«ENDIF»'''
140     
141     
142         /**
143      * Template method which generates JAVA comments.
144      * 
145      * @param comment string with the comment for whole JAVA class
146      * @return string with comment in JAVA format
147      */
148     def protected CharSequence asJavadoc(String comment) {
149         if (comment==null) return '';
150         val paragraphs = paragraphSplitter.split(comment)
151         
152         return '''
153             /**
154               «FOR p : paragraphs SEPARATOR "<p>"»
155               «p»
156               «ENDFOR»
157             **/
158             '''
159     }
160
161     def generateLengthRestrictions(Type type, String paramName) '''
162         «IF type instanceof ConcreteType»
163             «val restrictions = (type as ConcreteType).restrictions»
164             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
165                 «generateLengthRestriction(type, restrictions, paramName)»
166             «ENDIF»
167         «ENDIF»
168         «IF type instanceof GeneratedTransferObject»
169             «val restrictions = (type as GeneratedTransferObject).restrictions»
170             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
171                 «generateLengthRestriction(type, restrictions, paramName)»
172             «ENDIF»
173         «ENDIF»
174     '''
175
176     def generateLengthRestriction(Type type, Restrictions restrictions, String paramName) '''
177             boolean isValidLength = false;
178             «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>(); 
179             «FOR r : restrictions.lengthConstraints»
180                 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
181             «ENDFOR»
182             for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
183                 «IF type.name.contains("[")»
184                 if (r.contains(«paramName».length)) {
185                 «ELSE»
186                 if (r.contains(«paramName».length())) {
187                 «ENDIF»
188                     isValidLength = true;
189                 }
190             }
191             if (!isValidLength) {
192                 throw new IllegalArgumentException("illegal length");
193             }
194     '''
195
196 }