Bump versions to 13.0.4-SNAPSHOT
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / AbstractBuilderTemplate.xtend
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.java.api.generator
9
10 import java.util.ArrayList
11 import java.util.Collection
12 import java.util.Comparator
13 import java.util.List
14 import java.util.Set
15 import org.opendaylight.mdsal.binding.model.api.AnnotationType
16 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
17 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
18 import org.opendaylight.mdsal.binding.model.api.GeneratedType
19 import org.opendaylight.mdsal.binding.model.api.Type
20 import org.opendaylight.mdsal.binding.model.ri.BindingTypes
21 import org.opendaylight.yangtools.yang.binding.contract.Naming
22
23 abstract class AbstractBuilderTemplate extends BaseTemplate {
24     static val Comparator<GeneratedProperty> KEY_PROPS_COMPARATOR = [ p1, p2 | return p1.name.compareTo(p2.name) ]
25
26     /**
27      * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME.
28      */
29     protected val Type augmentType
30
31     /**
32      * Set of class attributes (fields) which are derived from the getter methods names.
33      */
34     protected val Set<BuilderGeneratedProperty> properties
35
36     /**
37      * GeneratedType for key type, null if this type does not have a key.
38      */
39     protected val Type keyType
40
41     protected val GeneratedType targetType;
42
43     new(AbstractJavaGeneratedType javaType, GeneratedType type, GeneratedType targetType,
44             Set<BuilderGeneratedProperty> properties, Type augmentType, Type keyType) {
45         super(javaType, type)
46         this.targetType = targetType
47         this.properties = properties
48         this.augmentType = augmentType
49         this.keyType = keyType
50     }
51
52     new(GeneratedType type, GeneratedType targetType, Type keyType) {
53         super(type)
54         this.targetType = targetType
55         this.keyType = keyType
56
57         val analysis = analyzeTypeHierarchy(targetType)
58         augmentType = analysis.key
59         properties = analysis.value
60     }
61
62     /**
63      * Template method which generates class attributes.
64      *
65      * @param makeFinal value which specify whether field is|isn't final
66      * @return string with class attributes and their types
67      */
68     def protected final generateFields(boolean makeFinal) '''
69         «IF properties !== null»
70             «FOR f : properties»
71                 private«IF makeFinal» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
72             «ENDFOR»
73         «ENDIF»
74         «IF keyType !== null»
75             private«IF makeFinal» final«ENDIF» «keyType.importedName» key;
76         «ENDIF»
77     '''
78
79     /**
80      * Template method which generate getter methods for IMPL class.
81      *
82      * @return string with getter methods
83      */
84     def final generateGetters(boolean addOverride) '''
85         «IF keyType !== null»
86             «IF addOverride»
87             @«OVERRIDE.importedName»
88             «ELSE»
89             /**
90              * Return current value associated with the property corresponding to {@link «targetType.importedName»#«Naming.KEY_AWARE_KEY_NAME»()}.
91              *
92              * @return current value
93              */
94             «ENDIF»
95             public «keyType.importedName» «Naming.KEY_AWARE_KEY_NAME»() {
96                 return key;
97             }
98
99         «ENDIF»
100         «IF !properties.empty»
101             «FOR field : properties SEPARATOR '\n'»
102                 «IF addOverride»
103                 @«OVERRIDE.importedName»
104                 «ELSE»
105                 /**
106                  * Return current value associated with the property corresponding to {@link «targetType.importedName»#«field.getterName»()}.
107                  *
108                  * @return current value
109                  */
110                 «ENDIF»
111                 «field.getterMethod»
112             «ENDFOR»
113         «ENDIF»
114     '''
115
116     def protected final CharSequence generateCopyConstructor(Type fromType, Type implType) '''
117         «type.name»(«fromType.importedName» base) {
118             «IF augmentType !== null»
119                 «generateCopyAugmentation(implType)»
120             «ENDIF»
121             «IF keyType !== null && implementsIfc(targetType, BindingTypes.keyAware(targetType))»
122                 «val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»
123                 «keyProps.sort(KEY_PROPS_COMPARATOR)»
124                 «val allProps = new ArrayList(properties)»
125                 «FOR field : keyProps»
126                     «removeProperty(allProps, field.name)»
127                 «ENDFOR»
128                 «generateCopyKeys(keyProps)»
129                 «generateCopyNonKeys(allProps)»
130             «ELSE»
131                 «generateCopyNonKeys(properties)»
132             «ENDIF»
133         }
134     '''
135
136     def protected final CharSequence generateDeprecatedAnnotation(List<AnnotationType> annotations) {
137         var AnnotationType found = annotations.findDeprecatedAnnotation
138         if (found === null) {
139             return ""
140         }
141         return generateDeprecatedAnnotation(found)
142     }
143
144     def protected abstract CharSequence generateCopyKeys(List<GeneratedProperty> keyProps)
145
146     def protected abstract CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props)
147
148     def protected abstract CharSequence generateCopyAugmentation(Type implType)
149
150     def protected abstract CharSequence generateDeprecatedAnnotation(AnnotationType ann)
151
152     private def boolean implementsIfc(GeneratedType type, Type impl) {
153         for (Type ifc : type.implements) {
154             if (ifc.equals(impl)) {
155                 return true;
156             }
157         }
158         return false;
159     }
160
161     private def void removeProperty(Collection<BuilderGeneratedProperty> props, String name) {
162         val iter = props.iterator
163         while (iter.hasNext) {
164             if (name.equals(iter.next.name)) {
165                 iter.remove
166                 return
167             }
168         }
169     }
170
171     private static def findDeprecatedAnnotation(List<AnnotationType> annotations) {
172         if (annotations !== null) {
173             for (annotation : annotations) {
174                 if (DEPRECATED.equals(annotation.identifier)) {
175                     return annotation
176                 }
177             }
178         }
179         return null
180     }
181
182     package static def hasNonDefaultMethods(GeneratedType type) {
183         !type.methodDefinitions.isEmpty && type.methodDefinitions.exists([def | !def.isDefault])
184     }
185
186     package static def nonDefaultMethods(GeneratedType type) {
187         type.methodDefinitions.filter([def | !def.isDefault])
188     }
189 }