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
\r
10 import java.util.List
\r
11 import org.opendaylight.yangtools.binding.generator.util.TypeConstants
\r
12 import org.opendaylight.yangtools.sal.binding.model.api.Constant
\r
13 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
\r
14 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
\r
15 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
\r
16 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
\r
17 import java.util.ArrayList
\r
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.
\r
29 class ClassTemplate extends BaseTemplate {
\r
31 protected val List<GeneratedProperty> properties
\r
32 protected val List<GeneratedProperty> finalProperties
\r
33 protected val List<GeneratedProperty> parentProperties
\r
34 protected val Iterable<GeneratedProperty> allProperties;
\r
35 protected val Restrictions restrictions
\r
38 * List of enumeration which are generated as JAVA enum type.
\r
40 protected val List<Enumeration> enums
\r
43 * List of constant instances which are generated as JAVA public static final attributes.
\r
45 protected val List<Constant> consts
\r
48 * List of generated types which are enclosed inside <code>genType</code>
\r
50 protected val List<GeneratedType> enclosedGeneratedTypes;
\r
53 protected val GeneratedTransferObject genTO;
\r
56 * Creates instance of this class with concrete <code>genType</code>.
\r
58 * @param genType generated transfer object which will be transformed to JAVA class source code
\r
60 new(GeneratedTransferObject genType) {
\r
62 this.genTO = genType
\r
63 this.properties = genType.properties
\r
64 this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)
\r
65 this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)
\r
66 this.restrictions = genType.restrictions
\r
68 var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();
\r
69 sorted.addAll(properties);
\r
70 sorted.addAll(parentProperties);
\r
71 Collections.sort(sorted, new PropertyComparator());
\r
73 this.allProperties = sorted
\r
74 this.enums = genType.enumerations
\r
75 this.consts = genType.constantDefinitions
\r
76 this.enclosedGeneratedTypes = genType.enclosedTypes
\r
81 * Generates JAVA class source code (class body only).
\r
83 * @return string with JAVA class body source code
\r
85 def CharSequence generateAsInnerClass() {
\r
86 return generateBody(true)
\r
90 override protected body() {
\r
91 generateBody(false);
\r
95 * Template method which generates class body.
\r
97 * @param isInnerClass boolean value which specify if generated class is|isn't inner
\r
98 * @return string with class source code in JAVA format
\r
100 def protected generateBody(boolean isInnerClass) '''
\r
101 «type.comment.asJavadoc»
\r
102 «generateClassDeclaration(isInnerClass)» {
\r
104 «innerClassesDeclarations»
\r
106 «constantsDeclarations»
\r
113 «FOR field : properties SEPARATOR "\n"»
\r
114 «field.getterMethod»
\r
115 «IF !field.readOnly»
\r
116 «field.setterMethod»
\r
124 «generateToString(genTO.toStringIdentifiers)»
\r
126 «generateGetLength»
\r
133 * Template method which generates inner classes inside this interface.
\r
135 * @return string with the source code for inner classes in JAVA format
\r
137 def protected innerClassesDeclarations() '''
\r
138 «IF !enclosedGeneratedTypes.empty»
\r
139 «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
\r
140 «IF (innerClass instanceof GeneratedTransferObject)»
\r
141 «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»
\r
142 «classTemplate.generateAsInnerClass»
\r
150 def protected constructors() '''
\r
151 «IF genTO.unionType»
\r
152 «genUnionConstructor»
\r
154 «allValuesConstructor»
\r
156 «IF !allProperties.empty»
\r
159 «IF properties.empty && !parentProperties.empty »
\r
160 «parentConstructor»
\r
164 def protected allValuesConstructor() '''
\r
165 «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
\r
166 @«ConstructorProperties.importedName»("value")
\r
168 public «type.name»(«allProperties.asArgumentsDeclaration») {
\r
169 «IF false == parentProperties.empty»
\r
170 super(«parentProperties.asArguments»);
\r
172 «FOR p : allProperties»
\r
173 «generateRestrictions(type, p.fieldName.toString, p.returnType)»
\r
175 «FOR p : properties»
\r
176 this.«p.fieldName» = «p.fieldName»;
\r
181 def protected genUnionConstructor() '''
\r
182 «FOR p : allProperties»
\r
183 «val List<GeneratedProperty> other = new ArrayList(properties)»
\r
184 «val added = other.remove(p)»
\r
185 «genConstructor(p, other)»
\r
190 def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''
\r
191 public «type.name»(«property.returnType.importedName + " " + property.name») {
\r
192 «IF false == parentProperties.empty»
\r
193 super(«parentProperties.asArguments»);
\r
195 «generateRestrictions(type, property.fieldName.toString, property.returnType)»
\r
196 this.«property.fieldName» = «property.name»;
\r
198 this.«p.fieldName» = null;
\r
203 def protected copyConstructor() '''
\r
205 * Creates a copy from Source Object.
\r
207 * @param source Source object
\r
209 public «type.name»(«type.name» source) {
\r
210 «IF false == parentProperties.empty»
\r
213 «FOR p : properties»
\r
214 this.«p.fieldName» = source.«p.fieldName»;
\r
219 def protected parentConstructor() '''
\r
221 * Creates a new instance from «genTO.superType.importedName»
\r
223 * @param source Source object
\r
225 public «type.name»(«genTO.superType.importedName» source) {
\r
230 def protected defaultInstance() '''
\r
231 «IF genTO.typedef && !allProperties.empty && !genTO.unionType»
\r
232 «val prop = allProperties.get(0)»
\r
233 «IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))»
\r
234 public static «genTO.name» getDefaultInstance(String defaultValue) {
\r
235 «IF "byte[]".equals(prop.returnType.name)»
\r
236 «BaseEncoding.importedName» baseEncoding = «BaseEncoding.importedName».base64();
\r
237 return new «genTO.name»(baseEncoding.decode(defaultValue));
\r
238 «ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)»
\r
239 return new «genTO.name»(defaultValue);
\r
240 «ELSEIF allProperties.size > 1»
\r
243 return new «genTO.name»(new «prop.returnType.importedName»(defaultValue));
\r
250 def protected bitsArgs() '''
\r
251 «List.importedName»<«String.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
\r
252 if (!properties.contains(defaultValue)) {
\r
253 throw new «IllegalArgumentException.importedName»("invalid default parameter");
\r
256 return new «genTO.name»(
\r
257 «FOR prop : allProperties SEPARATOR ","»
\r
258 properties.get(i++).equals(defaultValue) ? new «Boolean.importedName»("true") : null
\r
263 def protected propsAsArgs(Iterable<GeneratedProperty> properties) '''
\r
264 «FOR prop : properties SEPARATOR ","»
\r
270 * Template method which generates JAVA class declaration.
\r
272 * @param isInnerClass boolean value which specify if generated class is|isn't inner
\r
273 * @return string with class declaration in JAVA format
\r
275 def protected generateClassDeclaration(boolean isInnerClass) '''
\r
277 IF (isInnerClass)»«
\r
279 ELSEIF (type.abstract)»«
\r
283 ENDIF»class «type.name»«
\r
284 IF (genTO.superType != null)»«
\r
285 " extends "»«genTO.superType.importedName»«
\r
287 «IF (!type.implements.empty)»«
\r
289 FOR type : type.implements SEPARATOR ", "»«
\r
290 type.importedName»«
\r
296 * Template method which generates JAVA enum type.
\r
298 * @return string with inner enum source code in JAVA format
\r
300 def protected enumDeclarations() '''
\r
302 «FOR e : enums SEPARATOR "\n"»
\r
303 «val enumTemplate = new EnumTemplate(e)»
\r
304 «enumTemplate.generateAsInnerClass»
\r
309 def protected suidDeclaration() '''
\r
310 «IF genTO.SUID != null»
\r
311 private static final long serialVersionUID = «genTO.SUID.value»L;
\r
316 * Template method wich generates JAVA constants.
\r
318 * @return string with constants in JAVA format
\r
320 def protected constantsDeclarations() '''
\r
323 «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
\r
324 «val cValue = c.value»
\r
325 «IF cValue instanceof List<?>»
\r
326 «val cValues = cValue as List<?>»
\r
327 private static final «List.importedName»<«Pattern.importedName»> «Constants.MEMBER_PATTERN_LIST» = new «ArrayList.importedName»<«Pattern.importedName»>();
\r
328 public static final «List.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(«
\r
329 FOR v : cValues SEPARATOR ", "»«
\r
330 IF v instanceof String»"«
\r
335 «generateStaticInicializationBlock»
\r
338 public static final «c.type.importedName» «c.name» = «c.value»;
\r
345 * Template method which generates JAVA static initialization block.
\r
347 * @return string with static initialization block in JAVA format
\r
349 def protected generateStaticInicializationBlock() '''
\r
351 for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») {
\r
352 «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));
\r
358 * Template method which generates JAVA class attributes.
\r
360 * @return string with the class attributes in JAVA format
\r
362 def protected generateFields() '''
\r
363 «IF !properties.empty»
\r
364 «FOR f : properties»
\r
365 «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»;
\r
372 * Template method which generates the method <code>hashCode()</code>.
\r
374 * @return string with the <code>hashCode()</code> method definition in JAVA format
\r
376 def protected generateHashCode() '''
\r
377 «IF !genTO.hashCodeIdentifiers.empty»
\r
379 public int hashCode() {
\r
380 final int prime = 31;
\r
382 «FOR property : genTO.hashCodeIdentifiers»
\r
383 «IF property.returnType.name.contains("[")»
\r
384 result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»));
\r
386 result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode());
\r
395 * Template method which generates the method <code>equals()</code>.
\r
397 * @return string with the <code>equals()</code> method definition in JAVA format
\r
399 def protected generateEquals() '''
\r
400 «IF !genTO.equalsIdentifiers.empty»
\r
402 public boolean equals(java.lang.Object obj) {
\r
409 if (getClass() != obj.getClass()) {
\r
412 «type.name» other = («type.name») obj;
\r
413 «FOR property : genTO.equalsIdentifiers»
\r
414 «val fieldName = property.fieldName»
\r
415 if («fieldName» == null) {
\r
416 if (other.«fieldName» != null) {
\r
419 «IF property.returnType.name.contains("[")»
\r
420 } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {
\r
422 } else if(!«fieldName».equals(other.«fieldName»)) {
\r
432 def private generateGetLength() '''
\r
433 «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
\r
434 public static «List.importedName»<«Range.importedName»<Integer>> getLength() {
\r
435 final «List.importedName»<«Range.importedName»<Integer>> result = new «ArrayList.importedName»<>();
\r
436 «FOR r : restrictions.lengthConstraints»
\r
437 result.add(«Range.importedName».closed(«r.min», «r.max»));
\r
444 def private generateGetRange() '''
\r
445 «IF restrictions != null && !(restrictions.lengthConstraints.empty)»
\r
446 public static «List.importedName»<«Range.importedName»<Integer>> getLength() {
\r
447 final «List.importedName»<«Range.importedName»<Integer>> result = new «ArrayList.importedName»<>();
\r
448 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>();
\r
449 «FOR r : restrictions.lengthConstraints»
\r
450 result.add(«Range.importedName».closed(«r.min», «r.max»));
\r