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