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