Added export of augmentation schemas to Binding Context
[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 import java.util.Collection
17
18 abstract class BaseTemplate {
19     
20     
21     protected val GeneratedType type;
22     protected val Map<String,String> importMap;
23     static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
24     new(GeneratedType _type) {
25          if (_type== null) {
26             throw new IllegalArgumentException("Generated type reference cannot be NULL!")
27         }
28         this.type = _type;
29         this.importMap = GeneratorUtil.createImports(type)
30     }
31     
32     def packageDefinition () '''package «type.packageName»;'''
33
34
35     protected def getFullyQualifiedName() {
36         return type.fullyQualifiedName
37     }
38     
39     final public def generate() {
40     val _body = body()
41     '''
42     «packageDefinition»
43     «imports»
44
45     «_body»
46     '''.toString
47     }
48     protected def imports()  ''' 
49         «IF !importMap.empty»
50             «FOR entry : importMap.entrySet»
51                 «IF entry.value != fullyQualifiedName»
52                     import «entry.value».«entry.key»;
53                 «ENDIF»
54             «ENDFOR»
55         «ENDIF»
56
57     '''
58
59     protected abstract def CharSequence body();
60
61     // Helper patterns
62
63     final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
64
65
66     final protected def propertyNameFromGetter(MethodSignature getter) {
67         var int prefix;
68         if (getter.name.startsWith("is")) {
69             prefix = 2
70         } else if (getter.name.startsWith("get")) {
71             prefix = 3
72         } else {
73             throw new IllegalArgumentException("Not a getter")
74         }
75         return getter.name.substring(prefix).toFirstLower;
76     }
77
78     /**
79      * Template method which generates the getter method for <code>field</code>
80      * 
81      * @param field 
82      * generated property with data about field which is generated as the getter method
83      * @return string with the getter method source code in JAVA format 
84      */
85     final protected def getterMethod(GeneratedProperty field) {
86     '''
87         public «field.returnType.importedName» «field.getterMethodName»() {
88             return «field.fieldName»;
89         }
90     '''
91     }
92
93     final protected def getterMethodName(GeneratedProperty field) {
94         val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
95         return '''«prefix»«field.name.toFirstUpper»'''
96     }
97     
98     /**
99      * Template method which generates the setter method for <code>field</code>
100      * 
101      * @param field 
102      * generated property with data about field which is generated as the setter method
103      * @return string with the setter method source code in JAVA format 
104      */
105     final protected def setterMethod(GeneratedProperty field) '''
106         «val returnType = field.returnType.importedName»
107         public «type.name» set«field.name.toFirstUpper»(«returnType» value) {
108             this.«field.fieldName» = value;
109             return this;
110         }
111     '''
112     
113     final protected def importedName(Type intype) {
114         GeneratorUtil.putTypeIntoImports(type, intype, importMap);
115         GeneratorUtil.getExplicitType(type, intype, importMap)
116     }
117     
118     final protected def importedName(Class<?> cls) {
119         importedName(Types.typeForClass(cls))
120     }
121     
122     /**
123      * Template method which generates method parameters with their types from <code>parameters</code>.
124      * 
125      * @param parameters
126      * group of generated property instances which are transformed to the method parameters
127      * @return string with the list of the method parameters with their types in JAVA format
128      */
129     def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) 
130     '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
131     
132     /**
133      * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
134      * 
135      * @param parameters 
136      * group of generated property instances which are transformed to the sequence of parameter names
137      * @return string with the list of the parameter names of the <code>parameters</code> 
138      */
139     def final protected asArguments(Iterable<GeneratedProperty> parameters) 
140     '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.fieldName»«ENDFOR»«ENDIF»'''
141     
142     
143         /**
144      * Template method which generates JAVA comments.
145      * 
146      * @param comment string with the comment for whole JAVA class
147      * @return string with comment in JAVA format
148      */
149     def protected CharSequence asJavadoc(String comment) {
150         if (comment==null) return '';
151         val paragraphs = paragraphSplitter.split(comment)
152         
153         return '''
154             /**
155               «FOR p : paragraphs SEPARATOR "<p>"»
156               «p»
157               «ENDFOR»
158             **/
159             '''
160     }
161
162     def generateLengthRestrictions(Type type, String paramName, Type returnType) '''
163         «val boolean isArray = returnType.name.contains("[")»
164         «IF type instanceof ConcreteType»
165             «val restrictions = (type as ConcreteType).restrictions»
166             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
167                 «generateLengthRestriction(type, restrictions, paramName, isArray, !(returnType instanceof ConcreteType))»
168             «ENDIF»
169         «ENDIF»
170         «IF type instanceof GeneratedTransferObject»
171             «val restrictions = (type as GeneratedTransferObject).restrictions»
172             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
173                 «generateLengthRestriction(type, restrictions, paramName, isArray, !(returnType instanceof ConcreteType))»
174             «ENDIF»
175         «ENDIF»
176     '''
177
178     def generateLengthRestrictions(GeneratedProperty field, String paramName) '''
179         «val Type type = field.returnType»
180         «IF type instanceof ConcreteType»
181             «val boolean isArray = type.name.contains("[")»
182             «val restrictions = (type as ConcreteType).restrictions»
183             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
184                 «generateLengthRestriction(type, restrictions, paramName, isArray, false)»
185             «ENDIF»
186         «ENDIF»
187         «IF type instanceof GeneratedTransferObject»
188             «var isArray = isArrayType(type as GeneratedTransferObject)»
189             «val restrictions = (type as GeneratedTransferObject).restrictions»
190             «IF restrictions !== null && !restrictions.lengthConstraints.empty»
191                 «generateLengthRestriction(type, restrictions, paramName, isArray, true)»
192             «ENDIF»
193         «ENDIF»
194     '''
195
196     def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray, boolean isNestedType) '''
197         if («paramName» != null) {
198             boolean isValidLength = false;
199             «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>(); 
200             «FOR r : restrictions.lengthConstraints»
201                 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
202             «ENDFOR»
203             for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
204                 «IF isArray»
205                     «IF isNestedType»
206                         if (r.contains(«paramName».getValue().length)) {
207                     «ELSE»
208                         if (r.contains(«paramName».length)) {
209                     «ENDIF»
210                 «ELSE»
211                     «IF isNestedType»
212                         if (r.contains(«paramName».getValue().length())) {
213                     «ELSE»
214                         if (r.contains(«paramName».length())) {
215                     «ENDIF»
216                 «ENDIF»
217                     isValidLength = true;
218                 }
219             }
220             if (!isValidLength) {
221                 throw new IllegalArgumentException("illegal length");
222             }
223         }
224     '''
225
226     def GeneratedProperty getPropByName(GeneratedType gt, String name) {
227         for (GeneratedProperty prop : gt.properties) {
228             if (prop.name.equals(name)) {
229                 return prop;
230             }
231         }
232         return null;
233     }
234
235     def GeneratedProperty getPropByName(Collection<GeneratedProperty> props, String name) {
236         for (GeneratedProperty prop : props) {
237             if (prop.name.equals(name)) {
238                 return prop;
239             }
240         }
241         return null;
242     }
243
244     def boolean isArrayType(GeneratedTransferObject type) {
245         var isArray = false
246         val GeneratedTransferObject superType = type.findSuperType
247         val GeneratedProperty value = superType.getPropByName("value")
248         if (value != null && value.returnType.name.contains("[")) {
249             isArray = true
250         }
251         return isArray
252     }
253
254     def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
255         var GeneratedTransferObject base = gto
256         var GeneratedTransferObject superType = base.superType
257         while (superType !== null) {
258             base = superType
259             superType = base.superType
260         }
261         return base;
262     }
263
264 }