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