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