af55ac813fe9c2146af94dcac4c49fc01d376311
[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
2
3 import java.util.List
4 import java.util.Map
5 import org.opendaylight.yangtools.binding.generator.util.TypeConstants
6 import org.opendaylight.yangtools.sal.binding.model.api.Constant
7 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
8 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
9 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
10 import org.opendaylight.yangtools.sal.binding.model.api.Type
11 import org.opendaylight.yangtools.binding.generator.util.Types
12
13 class ClassTemplate {
14     
15     val GeneratedTransferObject genTO
16     val Map<String, String> imports
17     val List<GeneratedProperty> fields
18     val List<Enumeration> enums
19     val List<Constant> consts
20     
21     new(GeneratedTransferObject genTO) {
22         if (genTO == null) {
23             throw new IllegalArgumentException("Generated transfer object reference cannot be NULL!")
24         }
25         
26         this.genTO = genTO
27         this.imports = GeneratorUtil.createImports(genTO)
28         this.fields = genTO.properties
29         this.enums = genTO.enumerations
30         this.consts = genTO.constantDefinitions
31     }
32     
33     def String generate() {
34         val body = generateBody(false)
35         val pkgAndImports = generatePkgAndImports
36         return pkgAndImports.toString + body.toString
37     }
38     
39     def generateAsInnerClass() {
40         return generateBody(true)
41     }
42     
43     def private generateBody(boolean isInnerClass) '''
44         «genTO.comment.generateComment»
45         «generateClassDeclaration(isInnerClass)» {
46
47             «generateEnums»
48         
49             «generateConstants»
50         
51             «generateFields»
52         
53             «generateConstructor»
54         
55             «FOR field : fields SEPARATOR "\n"»
56                 «field.generateGetter»
57                 «IF !field.readOnly»
58                 
59                     «field.generateSetter»
60                 «ENDIF»
61             «ENDFOR»
62         
63             «generateHashCode»
64         
65             «generateEquals»
66         
67             «generateToString»
68         
69         }
70     '''
71     
72     def private generateComment(String comment) '''
73         «IF comment != null && !comment.empty»
74             /*
75             «comment»
76             */
77         «ENDIF»
78     '''
79     
80     def private generateClassDeclaration(boolean isInnerClass) '''
81         public«
82         IF (isInnerClass)»«
83             " static final "»«
84         ELSEIF (genTO.abstract)»«
85             " abstract "»«
86         ELSE»«
87             " "»«
88         ENDIF»class «genTO.name»«
89         IF (genTO.extends != null)»«
90             " extends "»«genTO.extends.resolveName»«
91         ENDIF»«
92         IF (!genTO.implements.empty)»«
93             " implements "»«
94             FOR type : genTO.implements SEPARATOR ", "»«
95                 type.resolveName»«
96             ENDFOR»«
97         ENDIF
98     »'''
99     
100     def private generateEnums() '''
101         «IF !enums.empty»
102             «FOR e : enums SEPARATOR "\n"»
103                 «val enumTemplate = new EnumTemplate(e)»
104                 «enumTemplate.generateAsInnerClass»
105             «ENDFOR»
106         «ENDIF»
107     '''
108     
109     def private generateConstants() '''
110         «IF !consts.empty»
111             «FOR c : consts»
112                 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
113                     «val cValue = c.value»
114                     «IF cValue instanceof List<?>»
115                         «val cValues = cValue as List<?>»
116                         private static final List<Pattern> «Constants.MEMBER_PATTERN_LIST» = new ArrayList<Pattern>();
117                         public static final List<String> «TypeConstants.PATTERN_CONSTANT_NAME» = Arrays.asList(«
118                         FOR v : cValues SEPARATOR ", "»«
119                             IF v instanceof String»"«
120                                 v as String»"«
121                             ENDIF»«
122                         ENDFOR»);
123                         
124                         «generateStaticInicializationBlock»
125                     «ENDIF»
126                 «ELSE»
127                     public static final «c.type.resolveName» «c.name» = «c.value»;
128                 «ENDIF»
129             «ENDFOR»
130         «ENDIF»
131     '''
132     
133     def private generateStaticInicializationBlock() '''
134         static {
135             for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
136                 «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));
137             }
138         }
139     '''
140     def private generateFields() '''
141         «IF !fields.empty»
142             «FOR f : fields»
143                 private «f.returnType.resolveName» «f.fieldName»;
144             «ENDFOR»
145         «ENDIF»
146     '''
147     
148     def private generateConstructor() '''
149         «val genTOTopParent = GeneratorUtil.getTopParrentTransportObject(genTO)»
150         «val properties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)»
151         «val propertiesAllParents = GeneratorUtil.getPropertiesOfAllParents(genTO)»
152         «IF !genTO.unionType»
153 «««            create constructor for every parent property
154             «IF genTOTopParent != genTO && genTOTopParent.unionType»
155                 «FOR parentProperty : propertiesAllParents SEPARATOR "\n"»
156                     «val parentPropertyAndProperties = properties + #[parentProperty]»
157                     «if (genTO.abstract) "protected" else "public"» «genTO.name»(«parentPropertyAndProperties.generateParameters») {
158                         super(«#[parentProperty].generateParameterNames»);
159                         «FOR property : properties»
160                             this.«property.fieldName» = «property.name»;
161                         «ENDFOR»
162                     }
163                 «ENDFOR»
164 «««            create one constructor
165             «ELSE»
166                 «val propertiesAll = propertiesAllParents + properties»
167                 «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertiesAll.generateParameters») {
168                     super(«propertiesAllParents.generateParameterNames()»);
169                     «FOR property : properties»
170                         this.«property.fieldName» = «property.fieldName»;
171                     «ENDFOR»
172                 }
173             «ENDIF»
174 «««        create constructor for every property
175         «ELSE»
176             «FOR property : properties SEPARATOR "\n"»
177                 «val propertyAndTopParentProperties = propertiesAllParents + #[property]»
178                 «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertyAndTopParentProperties.generateParameters») {
179                     super(«propertiesAllParents.generateParameterNames()»);
180                     this.«property.fieldName» = «property.fieldName»;
181                 }
182             «ENDFOR»
183         «ENDIF»
184     '''
185     
186     def private generateGetter(GeneratedProperty field) {
187         val prefix = if(field.returnType.equals(Types.typeForClass(Boolean))) "is" else "get"
188     '''
189         public «field.returnType.resolveName» «prefix»«field.name.toFirstUpper»() {
190             return «field.fieldName»;
191         }
192     '''
193     }
194     def private generateSetter(GeneratedProperty field) '''
195         «val type = field.returnType.resolveName»
196         public void set«field.name.toFirstUpper»(«type» «field.fieldName») {
197             this.«field.fieldName» = «field.fieldName»;
198         }
199     '''
200     
201     def private generateParameters(Iterable<GeneratedProperty> parameters) '''«
202         IF !parameters.empty»«
203             FOR parameter : parameters SEPARATOR ", "»«
204                 parameter.returnType.resolveName» «parameter.fieldName»«
205             ENDFOR»«
206         ENDIF
207     »'''
208     
209     def private generateParameterNames(Iterable<GeneratedProperty> parameters) '''«
210         IF !parameters.empty»«
211             FOR parameter : parameters SEPARATOR ", "»«
212                 parameter.fieldName»«
213             ENDFOR»«
214         ENDIF
215     »'''
216     
217     def private generateHashCode() '''
218         «IF !genTO.hashCodeIdentifiers.empty»
219             @Override
220             public int hashCode() {
221                 final int prime = 31;
222                 int result = 1;
223                 «FOR property : genTO.hashCodeIdentifiers»
224                     result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());
225                 «ENDFOR»
226                 return result;
227             }
228         «ENDIF»
229     '''
230     def private generateEquals() '''
231         «IF !genTO.equalsIdentifiers.empty»
232             @Override
233             public boolean equals(java.lang.Object obj) {
234                 if (this == obj) {
235                     return true;
236                 }
237                 if (obj == null) {
238                     return false;
239                 }
240                 if (getClass() != obj.getClass()) {
241                     return false;
242                 }
243                 «genTO.name» other = («genTO.name») obj;
244                 «FOR property : genTO.equalsIdentifiers»
245                     «val fieldName = property.fieldName»
246                     if («fieldName» == null) {
247                         if (other.«fieldName» != null) {
248                             return false;
249                         }
250                     } else if(!«fieldName».equals(other.«fieldName»)) {
251                         return false;
252                     }
253                 «ENDFOR»
254                 return true;
255             }
256         «ENDIF»
257     '''
258     
259     def private generateToString() '''
260         «IF !genTO.toStringIdentifiers.empty»
261             @Override
262             public String toString() {
263                 StringBuilder builder = new StringBuilder();
264                 «val properties = genTO.toStringIdentifiers»
265                 builder.append("«genTO.name» [«properties.get(0).fieldName»=");
266                 builder.append(«properties.get(0).fieldName»);
267                 «FOR i : 1..<genTO.toStringIdentifiers.size»
268                     builder.append(", «properties.get(i).fieldName»=");
269                     builder.append(«properties.get(i).fieldName»);
270                 «ENDFOR»
271                 builder.append("]");
272                 return builder.toString();
273             }
274         «ENDIF»
275     '''
276     
277     def private generatePkgAndImports() '''
278         package «genTO.packageName»;
279         
280         
281         «IF !imports.empty»
282             «FOR entry : imports.entrySet»
283                 import «entry.value».«entry.key»;
284             «ENDFOR»
285         «ENDIF»
286         
287     '''
288     
289     def private resolveName(Type type) {
290         GeneratorUtil.putTypeIntoImports(genTO, type, imports);
291         GeneratorUtil.getExplicitType(genTO, type, imports)
292     }
293     
294     def private fieldName(GeneratedProperty property) {
295         '''_«property.name»'''
296     }
297 }