1 package org.opendaylight.yangtools.sal.java.api.generator
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 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
15 * Template for generating JAVA class.
20 * Generated transfer object for which class JAVA file is generated
22 val GeneratedTransferObject genTO
25 * Map of imports for this <code>genTO</code>.
27 val Map<String, String> imports
30 * List of generated property instances which represents class attributes.
32 val List<GeneratedProperty> fields
35 * List of enumeration which are generated as JAVA enum type.
37 val List<Enumeration> enums
40 * List of constant instances which are generated as JAVA public static final attributes.
42 val List<Constant> consts
45 * List of generated types which are enclosed inside <code>genType</code>
47 val List<GeneratedType> enclosedGeneratedTypes;
50 * Creates instance of this class with concrete <code>genTO</code>.
52 * @param genTO generated transfer object which will be transformed to JAVA class source code
54 new(GeneratedTransferObject genTO) {
56 throw new IllegalArgumentException("Generated transfer object reference cannot be NULL!")
60 this.imports = GeneratorUtil.createImports(genTO)
61 this.fields = genTO.properties
62 this.enums = genTO.enumerations
63 this.consts = genTO.constantDefinitions
64 this.enclosedGeneratedTypes = genTO.enclosedTypes
68 * Generates JAVA class source code (package name + class body).
70 * @return string with JAVA class source code
72 def String generate() {
73 val body = generateBody(false)
74 val pkgAndImports = generatePkgAndImports
75 return pkgAndImports.toString + body.toString
79 * Generates JAVA class source code (class body only).
81 * @return string with JAVA class body source code
83 def generateAsInnerClass() {
84 return generateBody(true)
88 * Template method which generates class body.
90 * @param isInnerClass boolean value which specify if generated class is|isn't inner
91 * @return string with class source code in JAVA format
93 def private generateBody(boolean isInnerClass) '''
94 «genTO.comment.generateComment»
95 «generateClassDeclaration(isInnerClass)» {
96 «generateInnerClasses»
104 «generateConstructor»
106 «FOR field : fields SEPARATOR "\n"»
107 «field.generateGetter»
110 «field.generateSetter»
125 * Template method which generates inner classes inside this interface.
127 * @return string with the source code for inner classes in JAVA format
129 def private generateInnerClasses() '''
130 «IF !enclosedGeneratedTypes.empty»
131 «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
132 «IF (innerClass instanceof GeneratedTransferObject)»
133 «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»
134 «classTemplate.generateAsInnerClass»
142 * Template method which generates JAVA comments.
144 * @param string with the comment for whole JAVA class
145 * @return string with comment in JAVA format
147 def private generateComment(String comment) '''
148 «IF comment != null && !comment.empty»
156 * Template method which generates JAVA class declaration.
158 * @param isInnerClass boolean value which specify if generated class is|isn't inner
159 * @return string with class declaration in JAVA format
161 def private generateClassDeclaration(boolean isInnerClass) '''
165 ELSEIF (genTO.abstract)»«
169 ENDIF»class «genTO.name»«
170 IF (genTO.extends != null)»«
171 " extends "»«genTO.extends.resolveName»«
173 IF (!genTO.implements.empty)»«
175 FOR type : genTO.implements SEPARATOR ", "»«
182 * Template method which generates JAVA enum type.
184 * @return string with inner enum source code in JAVA format
186 def private generateEnums() '''
188 «FOR e : enums SEPARATOR "\n"»
189 «val enumTemplate = new EnumTemplate(e)»
190 «enumTemplate.generateAsInnerClass»
196 * Template method wich generates JAVA constants.
198 * @return string with constants in JAVA format
200 def private generateConstants() '''
203 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
204 «val cValue = c.value»
205 «IF cValue instanceof List<?>»
206 «val cValues = cValue as List<?>»
207 private static final List<Pattern> «Constants.MEMBER_PATTERN_LIST» = new ArrayList<Pattern>();
208 public static final List<String> «TypeConstants.PATTERN_CONSTANT_NAME» = Arrays.asList(«
209 FOR v : cValues SEPARATOR ", "»«
210 IF v instanceof String»"«
215 «generateStaticInicializationBlock»
218 public static final «c.type.resolveName» «c.name» = «c.value»;
225 * Template method which generates JAVA static initialization block.
227 * @return string with static initialization block in JAVA format
229 def private generateStaticInicializationBlock() '''
231 for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
232 «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));
238 * Template method which generates JAVA class attributes.
240 * @return string with the class attributes in JAVA format
242 def private generateFields() '''
245 private «f.returnType.resolveName» «f.fieldName»;
251 * Template method which generates JAVA constructor(s).
253 * @return string with the class constructor(s) in JAVA format
255 def private generateConstructor() '''
256 «val genTOTopParent = GeneratorUtil.getTopParrentTransportObject(genTO)»
257 «val properties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)»
258 «val propertiesAllParents = GeneratorUtil.getPropertiesOfAllParents(genTO)»
259 «IF !genTO.unionType»
260 ««« create constructor for every parent property
261 «IF genTOTopParent != genTO && genTOTopParent.unionType»
262 «FOR parentProperty : propertiesAllParents SEPARATOR "\n"»
263 «val parentPropertyAndProperties = properties + #[parentProperty]»
264 «if (genTO.abstract) "protected" else "public"» «genTO.name»(«parentPropertyAndProperties.generateParameters») {
265 super(«#[parentProperty].generateParameterNames»);
266 «FOR property : properties»
267 this.«property.fieldName» = «property.name»;
271 ««« create one constructor
273 «val propertiesAll = propertiesAllParents + properties»
274 «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertiesAll.generateParameters») {
275 super(«propertiesAllParents.generateParameterNames()»);
276 «FOR property : properties»
277 this.«property.fieldName» = «property.fieldName»;
281 ««« create constructor for every property
283 «FOR property : properties SEPARATOR "\n"»
284 «val propertyAndTopParentProperties = propertiesAllParents + #[property]»
285 «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertyAndTopParentProperties.generateParameters») {
286 super(«propertiesAllParents.generateParameterNames()»);
287 this.«property.fieldName» = «property.fieldName»;
294 * Template method which generates the getter method for <code>field</code>
297 * generated property with data about field which is generated as the getter method
298 * @return string with the getter method source code in JAVA format
300 def private generateGetter(GeneratedProperty field) {
301 val prefix = if(field.returnType.equals(Types.typeForClass(Boolean))) "is" else "get"
303 public «field.returnType.resolveName» «prefix»«field.name.toFirstUpper»() {
304 return «field.fieldName»;
310 * Template method which generates the setter method for <code>field</code>
313 * generated property with data about field which is generated as the setter method
314 * @return string with the setter method source code in JAVA format
316 def private generateSetter(GeneratedProperty field) '''
317 «val type = field.returnType.resolveName»
318 public void set«field.name.toFirstUpper»(«type» «field.fieldName») {
319 this.«field.fieldName» = «field.fieldName»;
324 * Template method which generates method parameters with their types from <code>parameters</code>.
327 * group of generated property instances which are transformed to the method parameters
328 * @return string with the list of the method parameters with their types in JAVA format
330 def private generateParameters(Iterable<GeneratedProperty> parameters) '''«
331 IF !parameters.empty»«
332 FOR parameter : parameters SEPARATOR ", "»«
333 parameter.returnType.resolveName» «parameter.fieldName»«
339 * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
342 * group of generated property instances which are transformed to the sequence of parameter names
343 * @return string with the list of the parameter names of the <code>parameters</code>
345 def private generateParameterNames(Iterable<GeneratedProperty> parameters) '''«
346 IF !parameters.empty»«
347 FOR parameter : parameters SEPARATOR ", "»«
348 parameter.fieldName»«
354 * Template method which generates the method <code>hashCode()</code>.
356 * @return string with the <code>hashCode()</code> method definition in JAVA format
358 def private generateHashCode() '''
359 «IF !genTO.hashCodeIdentifiers.empty»
361 public int hashCode() {
362 final int prime = 31;
364 «FOR property : genTO.hashCodeIdentifiers»
365 result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());
373 * Template method which generates the method <code>equals()</code>.
375 * @return string with the <code>equals()</code> method definition in JAVA format
377 def private generateEquals() '''
378 «IF !genTO.equalsIdentifiers.empty»
380 public boolean equals(java.lang.Object obj) {
387 if (getClass() != obj.getClass()) {
390 «genTO.name» other = («genTO.name») obj;
391 «FOR property : genTO.equalsIdentifiers»
392 «val fieldName = property.fieldName»
393 if («fieldName» == null) {
394 if (other.«fieldName» != null) {
397 } else if(!«fieldName».equals(other.«fieldName»)) {
407 * Template method which generates the method <code>toString()</code>.
409 * @return string with the <code>toString()</code> method definition in JAVA format
411 def private generateToString() '''
412 «IF !genTO.toStringIdentifiers.empty»
414 public String toString() {
415 StringBuilder builder = new StringBuilder();
416 «val properties = genTO.toStringIdentifiers»
417 builder.append("«genTO.name» [«properties.get(0).fieldName»=");
418 builder.append(«properties.get(0).fieldName»);
419 «FOR i : 1..<genTO.toStringIdentifiers.size»
420 builder.append(", «properties.get(i).fieldName»=");
421 builder.append(«properties.get(i).fieldName»);
424 return builder.toString();
430 * Template method which generate package name line and import lines.
432 * @result string with package and import lines in JAVA format
434 def private generatePkgAndImports() '''
435 package «genTO.packageName»;
439 «FOR entry : imports.entrySet»
440 import «entry.value».«entry.key»;
447 * Adds package to imports if it is necessary and returns necessary type name (with or without package name)
449 * @param type JAVA <code>Type</code>
450 * @return string with the type name (with or without package name)
452 def private resolveName(Type type) {
453 GeneratorUtil.putTypeIntoImports(genTO, type, imports);
454 GeneratorUtil.getExplicitType(genTO, type, imports)
457 def private fieldName(GeneratedProperty property) {
458 '''_«property.name»'''