Added check for valid length to typedef constructors.
[mdsal.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / ClassTemplate.xtend
1 package org.opendaylight.yangtools.sal.java.api.generator\r
2 \r
3 import java.util.List\r
4 import org.opendaylight.yangtools.binding.generator.util.TypeConstants\r
5 import org.opendaylight.yangtools.sal.binding.model.api.Constant\r
6 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration\r
7 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty\r
8 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject\r
9 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType\r
10 import java.util.ArrayList\r
11 import java.util.Collections\rimport java.util.Arrays
12 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
13 import com.google.common.collect.Range
14
15 /**\r
16  * Template for generating JAVA class. \r
17  */\r
18 class ClassTemplate extends BaseTemplate {\r
19 \r
20     protected val List<GeneratedProperty> properties\r
21     protected val List<GeneratedProperty> finalProperties\r
22     protected val List<GeneratedProperty> parentProperties\r
23     protected val Iterable<GeneratedProperty> allProperties;\r
24     protected val Restrictions restrictions\r
25     \r
26     /**\r
27      * List of enumeration which are generated as JAVA enum type.\r
28      */\r
29     protected val List<Enumeration> enums\r
30     \r
31     /**\r
32      * List of constant instances which are generated as JAVA public static final attributes.\r
33      */\r
34     protected val List<Constant> consts\r
35     \r
36     /**\r
37      * List of generated types which are enclosed inside <code>genType</code>\r
38      */\r
39     protected val List<GeneratedType> enclosedGeneratedTypes;\r
40     \r
41     \r
42     protected val GeneratedTransferObject genTO;\r
43 \r
44     /**\r
45      * Creates instance of this class with concrete <code>genType</code>.\r
46      * \r
47      * @param genType generated transfer object which will be transformed to JAVA class source code\r
48      */\r
49     new(GeneratedTransferObject genType) {\r
50         super(genType)\r
51         this.genTO = genType\r
52         this.properties = genType.properties\r
53         this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)\r
54         this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)\r
55         this.restrictions = genType.restrictions\r
56 \r
57         var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();\r
58         sorted.addAll(properties);\r
59         sorted.addAll(parentProperties);\r
60         Collections.sort(sorted, new PropertyComparator());\r
61 \r
62         this.allProperties = sorted\r
63         this.enums = genType.enumerations\r
64         this.consts = genType.constantDefinitions\r
65         this.enclosedGeneratedTypes = genType.enclosedTypes\r
66     }\r
67     \r
68 \r
69     \r
70     \r
71     \r
72     /**\r
73      * Generates JAVA class source code (class body only).\r
74      * \r
75      * @return string with JAVA class body source code\r
76      */\r
77     def CharSequence generateAsInnerClass() {\r
78         return generateBody(true)\r
79     }\r
80     \r
81 \r
82     \r
83     override protected body() {\r
84         generateBody(false);\r
85     }\r
86 \r
87     /**\r
88      * Template method which generates class body.\r
89      * \r
90      * @param isInnerClass boolean value which specify if generated class is|isn't inner\r
91      * @return string with class source code in JAVA format\r
92      */\r
93     def protected generateBody(boolean isInnerClass) '''\r
94         «type.comment.asJavadoc»\r
95         «generateClassDeclaration(isInnerClass)» {\r
96                 «innerClassesDeclarations»\r
97             «enumDeclarations»\r
98             «constantsDeclarations»\r
99             «generateFields»\r
100             «constructors»\r
101             «FOR field : properties SEPARATOR "\n"»\r
102                 «field.getterMethod»\r
103                 «IF !field.readOnly»\r
104                     «field.setterMethod»\r
105                 «ENDIF»\r
106             «ENDFOR»\r
107 \r
108             «generateHashCode»\r
109 \r
110             «generateEquals»\r
111 \r
112             «generateToString»\r
113 \r
114             «generateGetLength»\r
115 \r
116         }\r
117     '''\r
118     \r
119     \r
120     /**\r
121      * Template method which generates inner classes inside this interface.\r
122      * \r
123      * @return string with the source code for inner classes in JAVA format\r
124      */\r
125     def protected innerClassesDeclarations() '''\r
126         «IF !enclosedGeneratedTypes.empty»\r
127             «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»\r
128                 «IF (innerClass instanceof GeneratedTransferObject)»\r
129                     «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»\r
130                     «classTemplate.generateAsInnerClass»\r
131                     \r
132                 «ENDIF»\r
133             «ENDFOR»\r
134         «ENDIF»\r
135     '''\r
136     \r
137     \r
138     def protected constructors() '''\r
139         «IF genTO.unionType»\r
140             «genUnionConstructor»\r
141         «ELSE»\r
142             «allValuesConstructor»\r
143         «ENDIF»\r
144         «IF !allProperties.empty»\r
145             «copyConstructor»\r
146         «ENDIF»\r
147         «IF properties.empty && !parentProperties.empty »\r
148             «parentConstructor»\r
149         «ENDIF»\r
150     '''\r
151     \r
152     def protected allValuesConstructor() '''\r
153     public «type.name»(«allProperties.asArgumentsDeclaration») {\r
154         «IF false == parentProperties.empty»\r
155             super(«parentProperties.asArguments»);\r
156         «ENDIF»\r
157         «FOR p : allProperties» \r
158             «generateLengthRestrictions(type, p.fieldName.toString, p.returnType)»\r
159         «ENDFOR»\r
160         «FOR p : properties» \r
161             this.«p.fieldName» = «p.fieldName»;\r
162         «ENDFOR»\r
163     }\r
164     '''\r
165 \r
166     def protected genUnionConstructor() '''\r
167     «FOR p : allProperties»\r
168         «val List<GeneratedProperty> other = new ArrayList(properties)»\r
169         «val added = other.remove(p)»\r
170         «genConstructor(p, other)»\r
171     «ENDFOR»\r
172 \r
173     '''\r
174 \r
175     def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''\r
176     public «type.name»(«property.returnType.importedName + " " + property.name») {\r
177         «IF false == parentProperties.empty»\r
178             super(«parentProperties.asArguments»);\r
179         «ENDIF»\r
180             «generateLengthRestrictions(type, property.fieldName.toString, property.returnType)»\r
181             this.«property.fieldName» = «property.name»;\r
182             «FOR p : other»\r
183             this.«p.fieldName» = null;\r
184             «ENDFOR»\r
185     }\r
186     '''\r
187 \r
188     def protected copyConstructor() '''\r
189     /**\r
190      * Creates a copy from Source Object.\r
191      *\r
192      * @param source Source object\r
193      */\r
194     public «type.name»(«type.name» source) {\r
195         «IF false == parentProperties.empty»\r
196             super(source);\r
197         «ENDIF»\r
198         «FOR p : properties» \r
199             this.«p.fieldName» = source.«p.fieldName»;\r
200         «ENDFOR»\r
201     }\r
202     '''\r
203     \r
204     def protected parentConstructor() '''\r
205     /**\r
206      * Creates a new instance from «genTO.superType.importedName»\r
207      *\r
208      * @param source Source object\r
209      */\r
210     public «type.name»(«genTO.superType.importedName» source) {\r
211             super(source);\r
212     }\r
213     '''\r
214     \r
215 \r
216     \r
217     /**\r
218      * Template method which generates JAVA class declaration.\r
219      * \r
220      * @param isInnerClass boolean value which specify if generated class is|isn't inner\r
221      * @return string with class declaration in JAVA format\r
222      */\r
223     def protected generateClassDeclaration(boolean isInnerClass) '''\r
224         public«\r
225         IF (isInnerClass)»«\r
226             " static final "»«\r
227         ELSEIF (type.abstract)»«\r
228             " abstract "»«\r
229         ELSE»«\r
230             " "»«\r
231         ENDIF»class «type.name»«\r
232         IF (genTO.superType != null)»«\r
233             " extends "»«genTO.superType.importedName»«\r
234         ENDIF»\r
235         «IF (!type.implements.empty)»«\r
236             " implements "»«\r
237             FOR type : type.implements SEPARATOR ", "»«\r
238                 type.importedName»«\r
239             ENDFOR»«\r
240         ENDIF\r
241     »'''\r
242     \r
243     /**\r
244      * Template method which generates JAVA enum type.\r
245      * \r
246      * @return string with inner enum source code in JAVA format\r
247      */\r
248     def protected enumDeclarations() '''\r
249         «IF !enums.empty»\r
250             «FOR e : enums SEPARATOR "\n"»\r
251                 «val enumTemplate = new EnumTemplate(e)»\r
252                 «enumTemplate.generateAsInnerClass»\r
253             «ENDFOR»\r
254         «ENDIF»\r
255     '''\r
256     \r
257     /**\r
258      * Template method wich generates JAVA constants.\r
259      * \r
260      * @return string with constants in JAVA format \r
261      */\r
262     def protected constantsDeclarations() '''\r
263         «IF !consts.empty»\r
264             «FOR c : consts»\r
265                 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»\r
266                     «val cValue = c.value»\r
267                     «IF cValue instanceof List<?>»\r
268                         «val cValues = cValue as List<?>»\r
269                         private static final List<Pattern> «Constants.MEMBER_PATTERN_LIST» = new ArrayList<Pattern>();\r
270                         public static final List<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(«\r
271                         FOR v : cValues SEPARATOR ", "»«\r
272                             IF v instanceof String»"«\r
273                                 v as String»"«\r
274                             ENDIF»«\r
275                         ENDFOR»);\r
276 \r
277                         «generateStaticInicializationBlock»\r
278                     «ENDIF»\r
279                 «ELSE»\r
280                     public static final «c.type.importedName» «c.name» = «c.value»;\r
281                 «ENDIF»\r
282             «ENDFOR»\r
283         «ENDIF»\r
284     '''\r
285 \r
286     /**\r
287      * Template method which generates JAVA static initialization block.\r
288      *\r
289      * @return string with static initialization block in JAVA format\r
290      */\r
291     def protected generateStaticInicializationBlock() '''\r
292         static {\r
293             for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {\r
294                 «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));\r
295             }\r
296         }\r
297     '''\r
298 \r
299     /**\r
300      * Template method which generates JAVA class attributes.\r
301      *\r
302      * @return string with the class attributes in JAVA format\r
303      */\r
304     def protected generateFields() '''\r
305         «IF !properties.empty»\r
306             «FOR f : properties»\r
307                 «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»;\r
308             «ENDFOR»\r
309         «ENDIF»\r
310     '''\r
311 \r
312 \r
313     /**\r
314      * Template method which generates the method <code>hashCode()</code>.\r
315      *\r
316      * @return string with the <code>hashCode()</code> method definition in JAVA format\r
317      */\r
318     def protected generateHashCode() '''\r
319         «IF !genTO.hashCodeIdentifiers.empty»\r
320             @Override\r
321             public int hashCode() {\r
322                 final int prime = 31;\r
323                 int result = 1;\r
324                 «FOR property : genTO.hashCodeIdentifiers»\r
325                     «IF property.returnType.name.contains("[")»\r
326                     result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»));\r
327                     «ELSE»\r
328                     result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());\r
329                     «ENDIF»\r
330                 «ENDFOR»\r
331                 return result;\r
332             }\r
333         «ENDIF»\r
334     '''\r
335 \r
336     /**\r
337      * Template method which generates the method <code>equals()</code>.\r
338      *\r
339      * @return string with the <code>equals()</code> method definition in JAVA format\r
340      */\r
341     def protected generateEquals() '''\r
342         «IF !genTO.equalsIdentifiers.empty»\r
343             @Override\r
344             public boolean equals(java.lang.Object obj) {\r
345                 if (this == obj) {\r
346                     return true;\r
347                 }\r
348                 if (obj == null) {\r
349                     return false;\r
350                 }\r
351                 if (getClass() != obj.getClass()) {\r
352                     return false;\r
353                 }\r
354                 «type.name» other = («type.name») obj;\r
355                 «FOR property : genTO.equalsIdentifiers»\r
356                     «val fieldName = property.fieldName»\r
357                     if («fieldName» == null) {\r
358                         if (other.«fieldName» != null) {\r
359                             return false;\r
360                         }\r
361                     «IF property.returnType.name.contains("[")»\r
362                     } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {\r
363                     «ELSE»\r
364                     } else if(!«fieldName».equals(other.«fieldName»)) {\r
365                     «ENDIF»\r
366                         return false;\r
367                     }\r
368                 «ENDFOR»\r
369                 return true;\r
370             }\r
371         «ENDIF»\r
372     '''\r
373 \r
374     /**\r
375      * Template method which generates the method <code>toString()</code>.\r
376      *\r
377      * @return string with the <code>toString()</code> method definition in JAVA format\r
378      */\r
379     def protected generateToString() '''\r
380         «IF !genTO.toStringIdentifiers.empty»\r
381             @Override\r
382             public String toString() {\r
383                 StringBuilder builder = new StringBuilder();\r
384                 «val properties = genTO.toStringIdentifiers»\r
385                 builder.append("«type.name» [«properties.get(0).fieldName»=");\r
386                 «IF properties.get(0).returnType.name.contains("[")»\r
387                     builder.append(«Arrays.importedName».toString(«properties.get(0).fieldName»));\r
388                 «ELSE»\r
389                     builder.append(«properties.get(0).fieldName»);\r
390                 «ENDIF»\r
391                 «FOR i : 1..<genTO.toStringIdentifiers.size»\r
392                     builder.append(", «properties.get(i).fieldName»=");\r
393                     «IF properties.get(i).returnType.name.contains("[")»\r
394                         builder.append(«Arrays.importedName».toString(«properties.get(i).fieldName»));\r
395                     «ELSE»\r
396                         builder.append(«properties.get(i).fieldName»);\r
397                     «ENDIF»\r
398                 «ENDFOR»\r
399                 builder.append("]");\r
400                 return builder.toString();\r
401             }\r
402         «ENDIF»\r
403     '''\r
404 \r
405     def private generateGetLength() '''\r
406         «IF restrictions != null && !(restrictions.lengthConstraints.empty)»\r
407             public static «List.importedName»<«Range.importedName»<Integer>> getLength() {\r
408                 final «List.importedName»<«Range.importedName»<Integer>> result = new «ArrayList.importedName»<>();\r
409                 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>(); \r
410                 «FOR r : restrictions.lengthConstraints»\r
411                     result.add(«Range.importedName».closed(«r.min», «r.max»));\r
412                 «ENDFOR»\r
413                 return result;\r
414             }\r
415         «ENDIF»\r
416     '''\r
417 \r
418 }\r