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