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