2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.sal.java.api.generator
11 import org.opendaylight.yangtools.binding.generator.util.TypeConstants
12 import org.opendaylight.yangtools.sal.binding.model.api.Constant
13 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
14 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
15 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
16 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
17 import java.util.ArrayList
18 import java.util.Collections
\rimport java.util.Arrays
19 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
20 import com.google.common.collect.Range
21 import java.util.regex.Pattern
22 import com.google.common.io.BaseEncoding
23 import java.beans.ConstructorProperties
24 import com.google.common.collect.Lists
27 * Template for generating JAVA class.
29 class ClassTemplate extends BaseTemplate {
31 protected val List<GeneratedProperty> properties
32 protected val List<GeneratedProperty> finalProperties
33 protected val List<GeneratedProperty> parentProperties
34 protected val Iterable<GeneratedProperty> allProperties;
35 protected val Restrictions restrictions
38 * List of enumeration which are generated as JAVA enum type.
40 protected val List<Enumeration> enums
43 * List of constant instances which are generated as JAVA public static final attributes.
45 protected val List<Constant> consts
48 * List of generated types which are enclosed inside <code>genType</code>
50 protected val List<GeneratedType> enclosedGeneratedTypes;
53 protected val GeneratedTransferObject genTO;
56 * Creates instance of this class with concrete <code>genType</code>.
58 * @param genType generated transfer object which will be transformed to JAVA class source code
60 new(GeneratedTransferObject genType) {
63 this.properties = genType.properties
64 this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)
65 this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)
66 this.restrictions = genType.restrictions
68 var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();
69 sorted.addAll(properties);
70 sorted.addAll(parentProperties);
71 Collections.sort(sorted, [p1, p2|
72 p1.name.compareTo(p2.name)
75 this.allProperties = sorted
76 this.enums = genType.enumerations
77 this.consts = genType.constantDefinitions
78 this.enclosedGeneratedTypes = genType.enclosedTypes
83 * Generates JAVA class source code (class body only).
85 * @return string with JAVA class body source code
87 def CharSequence generateAsInnerClass() {
88 return generateBody(true)
92 override protected body() {
97 * Template method which generates class body.
99 * @param isInnerClass boolean value which specify if generated class is|isn't inner
100 * @return string with class source code in JAVA format
102 def protected generateBody(boolean isInnerClass) '''
103 «type.comment.asJavadoc»
104 «generateClassDeclaration(isInnerClass)» {
106 «innerClassesDeclarations»
108 «constantsDeclarations»
115 «FOR field : properties SEPARATOR "\n"»
126 «generateToString(genTO.toStringIdentifiers)»
128 «generateLengthMethod("length", genTO, genTO.importedName, "_length")»
130 «generateRangeMethod("range", genTO, genTO.importedName, "_range")»
137 * Template method which generates inner classes inside this interface.
139 * @return string with the source code for inner classes in JAVA format
141 def protected innerClassesDeclarations() '''
142 «IF !enclosedGeneratedTypes.empty»
143 «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
144 «IF (innerClass instanceof GeneratedTransferObject)»
145 «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»
146 «classTemplate.generateAsInnerClass»
154 def protected constructors() '''
156 «genUnionConstructor»
158 «allValuesConstructor»
160 «IF !allProperties.empty»
163 «IF properties.empty && !parentProperties.empty »
168 def protected allValuesConstructor() '''
169 «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
170 @«ConstructorProperties.importedName»("value")
172 public «type.name»(«allProperties.asArgumentsDeclaration») {
173 «IF false == parentProperties.empty»
174 super(«parentProperties.asArguments»);
176 «FOR p : allProperties»
177 «generateRestrictions(type, p.fieldName.toString, p.returnType)»
180 this.«p.fieldName» = «p.fieldName»;
185 def protected genUnionConstructor() '''
186 «FOR p : allProperties»
187 «val List<GeneratedProperty> other = new ArrayList(properties)»
189 «genConstructor(p, other)»
195 def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''
196 public «type.name»(«property.returnType.importedName + " " + property.name») {
197 «IF false == parentProperties.empty»
198 super(«parentProperties.asArguments»);
200 «generateRestrictions(type, property.fieldName.toString, property.returnType)»
201 this.«property.fieldName» = «property.name»;
203 this.«p.fieldName» = null;
208 def protected copyConstructor() '''
210 * Creates a copy from Source Object.
212 * @param source Source object
214 public «type.name»(«type.name» source) {
215 «IF false == parentProperties.empty»
219 this.«p.fieldName» = source.«p.fieldName»;
224 def protected parentConstructor() '''
226 * Creates a new instance from «genTO.superType.importedName»
228 * @param source Source object
230 public «type.name»(«genTO.superType.importedName» source) {
235 def protected defaultInstance() '''
236 «IF genTO.typedef && !allProperties.empty && !genTO.unionType»
237 «val prop = allProperties.get(0)»
238 «IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))»
239 public static «genTO.name» getDefaultInstance(String defaultValue) {
240 «IF "byte[]".equals(prop.returnType.name)»
241 «BaseEncoding.importedName» baseEncoding = «BaseEncoding.importedName».base64();
242 return new «genTO.name»(baseEncoding.decode(defaultValue));
243 «ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)»
244 return new «genTO.name»(defaultValue);
245 «ELSEIF allProperties.size > 1»
248 return new «genTO.name»(new «prop.returnType.importedName»(defaultValue));
255 def protected bitsArgs() '''
256 «List.importedName»<«String.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
257 if (!properties.contains(defaultValue)) {
258 throw new «IllegalArgumentException.importedName»("invalid default parameter");
261 return new «genTO.name»(
262 «FOR prop : allProperties SEPARATOR ","»
263 properties.get(i++).equals(defaultValue) ? new «Boolean.importedName»("true") : null
268 def protected propsAsArgs(Iterable<GeneratedProperty> properties) '''
269 «FOR prop : properties SEPARATOR ","»
275 * Template method which generates JAVA class declaration.
277 * @param isInnerClass boolean value which specify if generated class is|isn't inner
278 * @return string with class declaration in JAVA format
280 def protected generateClassDeclaration(boolean isInnerClass) '''
284 ELSEIF (type.abstract)»«
288 ENDIF»class «type.name»«
289 IF (genTO.superType != null)»«
290 " extends "»«genTO.superType.importedName»«
292 «IF (!type.implements.empty)»«
294 FOR type : type.implements SEPARATOR ", "»«
301 * Template method which generates JAVA enum type.
303 * @return string with inner enum source code in JAVA format
305 def protected enumDeclarations() '''
307 «FOR e : enums SEPARATOR "\n"»
308 «val enumTemplate = new EnumTemplate(e)»
309 «enumTemplate.generateAsInnerClass»
314 def protected suidDeclaration() '''
315 «IF genTO.SUID != null»
316 private static final long serialVersionUID = «genTO.SUID.value»L;
321 * Template method wich generates JAVA constants.
323 * @return string with constants in JAVA format
325 def protected constantsDeclarations() '''
328 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
329 «val cValue = c.value»
330 «IF cValue instanceof List<?>»
331 «val cValues = cValue as List<?>»
332 private static final «List.importedName»<«Pattern.importedName»> «Constants.MEMBER_PATTERN_LIST» = new «ArrayList.importedName»<«Pattern.importedName»>();
333 public static final «List.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(«
334 FOR v : cValues SEPARATOR ", "»«
335 IF v instanceof String»"«
340 «generateStaticInicializationBlock»
343 public static final «c.type.importedName» «c.name» = «c.value»;
350 * Template method which generates JAVA static initialization block.
352 * @return string with static initialization block in JAVA format
354 def protected generateStaticInicializationBlock() '''
356 for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
357 «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));
363 * Template method which generates JAVA class attributes.
365 * @return string with the class attributes in JAVA format
367 def protected generateFields() '''
368 «IF restrictions != null»
369 «IF !(restrictions.lengthConstraints.empty)»
370 «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
371 private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _length;
373 «IF !(restrictions.rangeConstraints.empty)»
374 «val numberClass = restrictions.rangeConstraints.iterator.next.min.class»
375 private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _range;
378 «IF !properties.empty»
380 «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»;
387 * Template method which generates the method <code>hashCode()</code>.
389 * @return string with the <code>hashCode()</code> method definition in JAVA format
391 def protected generateHashCode() '''
392 «IF !genTO.hashCodeIdentifiers.empty»
394 public int hashCode() {
395 final int prime = 31;
397 «FOR property : genTO.hashCodeIdentifiers»
398 «IF property.returnType.name.contains("[")»
399 result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»));
401 result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());
410 * Template method which generates the method <code>equals()</code>.
412 * @return string with the <code>equals()</code> method definition in JAVA format
414 def protected generateEquals() '''
415 «IF !genTO.equalsIdentifiers.empty»
417 public boolean equals(java.lang.Object obj) {
424 if (getClass() != obj.getClass()) {
427 «type.name» other = («type.name») obj;
428 «FOR property : genTO.equalsIdentifiers»
429 «val fieldName = property.fieldName»
430 if («fieldName» == null) {
431 if (other.«fieldName» != null) {
434 «IF property.returnType.name.contains("[")»
435 } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {
437 } else if(!«fieldName».equals(other.«fieldName»)) {