1 package org.opendaylight.yangtools.sal.java.api.generator
\r
3 import java.util.LinkedHashSet
\r
4 import java.util.List
\r
7 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
\r
8 import org.opendaylight.yangtools.binding.generator.util.Types
\r
9 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl
\r
10 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
\r
11 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
\r
12 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
\r
13 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
\r
14 import org.opendaylight.yangtools.sal.binding.model.api.Type
\r
15 import org.opendaylight.yangtools.yang.binding.Augmentable
\r
16 import static org.opendaylight.yangtools.binding.generator.util.Types.*
\r
17 import java.util.HashMap
\r
18 import java.util.Collections
\r
21 * Template for generating JAVA builder classes.
\r
24 class BuilderTemplate extends BaseTemplate {
\r
26 * Constant with prefix for getter methods.
\r
28 val static GET_PREFIX = "get"
\r
32 * Constant with the name of the concrete package prefix.
\r
34 val static JAVA_UTIL = "java.util"
\r
37 * Constant with the name of the concrete JAVA type
\r
39 val static HASH_MAP = "HashMap"
\r
42 * Constant with the name of the concrete JAVA interface.
\r
44 val static MAP = "Map"
\r
47 * Constant with the name of the concrete method.
\r
49 val static GET_AUGMENTATION_METHOD_NAME = "getAugmentation"
\r
52 * Constant with the suffix for builder classes.
\r
54 val static BUILDER = 'Builder'
\r
57 * Constant with suffix for the classes which are generated from the builder classes.
\r
59 val static IMPL = 'Impl'
\r
62 * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME
\r
64 var GeneratedProperty augmentField
\r
67 * Set of class attributes (fields) which are derived from the getter methods names
\r
69 val Set<GeneratedProperty> properties
\r
72 * Constructs new instance of this class.
\r
73 * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
\r
75 new(GeneratedType genType) {
\r
77 this.properties = propertiesFromMethods(createMethods)
\r
81 * Returns set of method signature instances which contains all the methods of the <code>genType</code>
\r
82 * and all the methods of the implemented interfaces.
\r
84 * @returns set of method signature instances
\r
86 def private Set<MethodSignature> createMethods() {
\r
87 val Set<MethodSignature> methods = new LinkedHashSet
\r
88 methods.addAll(type.methodDefinitions)
\r
89 collectImplementedMethods(methods, type.implements)
\r
95 * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code>
\r
96 * and recursivelly their implemented interfaces.
\r
98 * @param methods set of method signatures
\r
99 * @param implementedIfcs list of implemented interfaces
\r
101 def private void collectImplementedMethods(Set<MethodSignature> methods, List<Type> implementedIfcs) {
\r
102 if (implementedIfcs == null || implementedIfcs.empty) {
\r
105 for (implementedIfc : implementedIfcs) {
\r
106 if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
\r
107 val ifc = implementedIfc as GeneratedType
\r
108 methods.addAll(ifc.methodDefinitions)
\r
109 collectImplementedMethods(methods, ifc.implements)
\r
110 } else if (implementedIfc.fullyQualifiedName == Augmentable.name) {
\r
111 for (m : Augmentable.methods) {
\r
112 if (m.name == GET_AUGMENTATION_METHOD_NAME) {
\r
113 //addToImports(JAVA_UTIL, HASH_MAP)
\r
114 //addToImports(JAVA_UTIL, MAP)
\r
115 val fullyQualifiedName = m.returnType.name
\r
116 val pkg = fullyQualifiedName.package
\r
117 val name = fullyQualifiedName.name
\r
118 //addToImports(pkg, name)
\r
119 val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)
\r
120 val refType = new ReferencedTypeImpl(pkg, name)
\r
121 val generic = new ReferencedTypeImpl(type.packageName, type.name)
\r
122 val parametrizedReturnType = Types.parameterizedTypeFor(refType, generic)
\r
123 tmpGenTO.addMethod(m.name).setReturnType(parametrizedReturnType)
\r
124 augmentField = tmpGenTO.toInstance.methodDefinitions.first.propertyFromGetter
\r
133 * Returns the first element of the list <code>elements</code>.
\r
135 * @param list of elements
\r
137 def private <E> first(List<E> elements) {
\r
142 * Returns the name of the package from <code>fullyQualifiedName</code>.
\r
144 * @param fullyQualifiedName string with fully qualified type name (package + type)
\r
145 * @return string with the package name
\r
147 def private String getPackage(String fullyQualifiedName) {
\r
148 val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
\r
149 return if (lastDotIndex == -1) "" else fullyQualifiedName.substring(0, lastDotIndex)
\r
153 * Returns the name of tye type from <code>fullyQualifiedName</code>
\r
155 * @param fullyQualifiedName string with fully qualified type name (package + type)
\r
156 * @return string with the name of the type
\r
158 def private String getName(String fullyQualifiedName) {
\r
159 val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
\r
160 return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)
\r
165 * Creates set of generated property instances from getter <code>methods</code>.
\r
167 * @param set of method signature instances which should be transformed to list of properties
\r
168 * @return set of generated property instances which represents the getter <code>methods</code>
\r
170 def private propertiesFromMethods(Set<MethodSignature> methods) {
\r
173 if (methods == null || methods.isEmpty()) {
\r
174 return Collections.emptySet
\r
176 val Set<GeneratedProperty> result = new LinkedHashSet
\r
177 for (m : methods) {
\r
178 val createdField = m.propertyFromGetter
\r
179 if (createdField != null) {
\r
180 result.add(createdField)
\r
187 * Creates generated property instance from the getter <code>method</code> name and return type.
\r
189 * @param method method signature from which is the method name and return type obtained
\r
190 * @return generated property instance for the getter <code>method</code>
\r
191 * @throws IllegalArgumentException<ul>
\r
192 * <li>if the <code>method</code> equals <code>null</code></li>
\r
193 * <li>if the name of the <code>method</code> equals <code>null</code></li>
\r
194 * <li>if the name of the <code>method</code> is empty</li>
\r
195 * <li>if the return type of the <code>method</code> equals <code>null</code></li>
\r
198 def private GeneratedProperty propertyFromGetter(MethodSignature method) {
\r
200 if (method == null || method.name == null || method.name.empty || method.returnType == null) {
\r
201 throw new IllegalArgumentException("Method, method name, method return type reference cannot be NULL or empty!")
\r
203 var prefix = "get";
\r
204 if(BOOLEAN.equals(method.returnType)) {
\r
207 if (method.name.startsWith(prefix)) {
\r
208 val fieldName = method.getName().substring(prefix.length()).toFirstLower
\r
209 val tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo")
\r
210 tmpGenTO.addProperty(fieldName).setReturnType(method.returnType)
\r
211 return tmpGenTO.toInstance.properties.first
\r
216 * Template method which generates JAVA class body for builder class and for IMPL class.
\r
218 * @return string with JAVA source code
\r
220 override body() '''
\r
222 public class «type.name»«BUILDER» {
\r
224 «generateFields(false)»
\r
226 «generateGetters(false)»
\r
231 public «type.name» build() {
\r
232 return new «type.name»«IMPL»(this);
\r
235 private static class «type.name»«IMPL» implements «type.name» {
\r
237 «generateFields(true)»
\r
239 «generateConstructor»
\r
241 «generateGetters(true)»
\r
249 * Template method which generates class attributes.
\r
251 * @param boolean value which specify whether field is|isn't final
\r
252 * @return string with class attributes and their types
\r
254 def private generateFields(boolean _final) '''
\r
255 «IF !properties.empty»
\r
256 «FOR f : properties»
\r
257 private «IF _final»final«ENDIF» «f.returnType.importedName» «f.fieldName»;
\r
260 «IF augmentField != null»
\r
261 private «Map.importedName»<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();
\r
266 * Template method which generates setter methods
\r
268 * @return string with the setter methods
\r
270 def private generateSetters() '''
\r
271 «FOR field : properties SEPARATOR '\n'»
\r
272 public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {
\r
273 this.«field.fieldName» = value;
\r
277 «IF augmentField != null»
\r
279 public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(Class<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {
\r
280 this.«augmentField.name».put(augmentationType, augmentation);
\r
287 * Template method which generate constructor for IMPL class.
\r
289 * @return string with IMPL class constructor
\r
291 def private generateConstructor() '''
\r
292 private «type.name»«IMPL»(«type.name»«BUILDER» builder) {
\r
293 «IF !properties.empty»
\r
294 «FOR field : properties»
\r
295 this.«field.fieldName» = builder.«field.fieldName»;
\r
298 «IF augmentField != null»
\r
299 this.«augmentField.name».putAll(builder.«augmentField.name»);
\r
306 * Template method which generate getter methods for IMPL class.
\r
308 * @return string with getter methods
\r
310 def private generateGetters(boolean addOverride) '''
\r
311 «IF !properties.empty»
\r
312 «FOR field : properties SEPARATOR '\n'»
\r
313 «IF addOverride»@Override«ENDIF»
\r
314 «field.getterMethod»
\r
317 «IF augmentField != null»
\r
319 @SuppressWarnings("unchecked")
\r
320 «IF addOverride»@Override«ENDIF»
\r
321 public <E extends «augmentField.returnType.importedName»> E get«augmentField.name.toFirstUpper»(Class<E> augmentationType) {
\r
322 if (augmentationType == null) {
\r
323 throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
\r
325 return (E) «augmentField.name».get(augmentationType);
\r