Use ArrayList.sort() instead of Collections.sort()
[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.AUGMENTABLE_AUGMENTATION_NAME
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.List
18 import java.util.Map
19 import java.util.Set
20 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
21 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
22 import org.opendaylight.mdsal.binding.model.api.GeneratedType
23 import org.opendaylight.mdsal.binding.model.api.Type
24 import org.opendaylight.mdsal.binding.model.util.Types
25 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
26 import org.opendaylight.yangtools.yang.binding.CodeHelpers
27 import org.opendaylight.yangtools.yang.binding.Identifiable
28
29 abstract class AbstractBuilderTemplate extends BaseTemplate {
30     /**
31      * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME.
32      */
33     protected val Type augmentType
34
35     /**
36      * Set of class attributes (fields) which are derived from the getter methods names.
37      */
38     protected val Set<GeneratedProperty> properties
39
40     /**
41      * GeneratedType for key type, null if this type does not have a key.
42      */
43     protected val Type keyType
44
45     protected val GeneratedType targetType;
46
47     new(AbstractJavaGeneratedType javaType, GeneratedType type, GeneratedType targetType,
48             Set<GeneratedProperty> properties, Type augmentType, Type keyType) {
49         super(javaType, type)
50         this.targetType = targetType
51         this.properties = properties
52         this.augmentType = augmentType
53         this.keyType = keyType
54     }
55
56     new(GeneratedType type, GeneratedType targetType, Set<GeneratedProperty> properties, Type augmentType,
57             Type keyType) {
58         super(type)
59         this.targetType = targetType
60         this.properties = properties
61         this.augmentType = augmentType
62         this.keyType = keyType
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(boolean isPrivate) '''
83         «IF augmentType !== null»
84             «IF isPrivate»private «ENDIF»«Map.importedName»<«Class.importedName»<? extends «augmentType.importedName»>, «augmentType.importedName»> «AUGMENTATION_FIELD» = «Collections.importedName».emptyMap();
85         «ENDIF»
86     '''
87
88     override generateToString(Collection<GeneratedProperty> properties) '''
89         «IF properties !== null»
90             @«Override.importedName»
91             public «String.importedName» toString() {
92                 final «MoreObjects.importedName».ToStringHelper helper = «MoreObjects.importedName».toStringHelper("«targetType.name»");
93                 «FOR property : properties»
94                     «CodeHelpers.importedName».appendValue(helper, "«property.fieldName»", «property.fieldName»);
95                 «ENDFOR»
96                 «IF augmentType !== null»
97                     «CodeHelpers.importedName».appendValue(helper, "«AUGMENTATION_FIELD»", «AUGMENTATION_FIELD».values());
98                 «ENDIF»
99                 return helper.toString();
100             }
101         «ENDIF»
102     '''
103
104     /**
105      * Template method which generate getter methods for IMPL class.
106      *
107      * @return string with getter methods
108      */
109     def final generateGetters(boolean addOverride) '''
110         «IF keyType !== null»
111             «IF addOverride»@«Override.importedName»«ENDIF»
112             public «keyType.importedName» «BindingMapping.IDENTIFIABLE_KEY_NAME»() {
113                 return key;
114             }
115
116         «ENDIF»
117         «IF !properties.empty»
118             «FOR field : properties SEPARATOR '\n'»
119                 «IF addOverride»@«Override.importedName»«ENDIF»
120                 «field.getterMethod»
121             «ENDFOR»
122         «ENDIF»
123         «IF augmentType !== null»
124
125             @SuppressWarnings("unchecked")
126             «IF addOverride»@«Override.importedName»«ENDIF»
127             public <E extends «augmentType.importedName»> E «AUGMENTABLE_AUGMENTATION_NAME»(«Class.importedName»<E> augmentationType) {
128                 return (E) «AUGMENTATION_FIELD».get(«CodeHelpers.importedName».nonNullValue(augmentationType, "augmentationType"));
129             }
130         «ENDIF»
131     '''
132
133     def protected final CharSequence generateCopyConstructor(Type fromType, Type implType) '''
134         «type.name»(«fromType.importedName» base) {
135             «val allProps = new ArrayList(properties)»
136             «val isList = implementsIfc(targetType, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), targetType))»
137             «IF isList && keyType !== null»
138                 «val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»
139                 «keyProps.sort([ p1, p2 | return p1.name.compareTo(p2.name) ])»
140                 «FOR field : keyProps»
141                     «removeProperty(allProps, field.name)»
142                 «ENDFOR»
143                 «generateCopyKeys(keyProps)»
144             «ENDIF»
145             «FOR field : allProps»
146                 this.«field.fieldName» = base.«field.getterMethodName»();
147             «ENDFOR»
148             «IF augmentType !== null»
149                 «generateCopyAugmentation(implType)»
150             «ENDIF»
151         }
152     '''
153
154     def protected abstract CharSequence generateCopyKeys(List<GeneratedProperty> keyProps)
155
156     def protected abstract CharSequence generateCopyAugmentation(Type implType);
157
158     private def boolean implementsIfc(GeneratedType type, Type impl) {
159         for (Type ifc : type.implements) {
160             if (ifc.equals(impl)) {
161                 return true;
162             }
163         }
164         return false;
165     }
166
167     private def void removeProperty(Collection<GeneratedProperty> props, String name) {
168         var GeneratedProperty toRemove = null
169         for (p : props) {
170             if (p.name.equals(name)) {
171                 toRemove = p;
172             }
173         }
174         if (toRemove !== null) {
175             props.remove(toRemove);
176         }
177     }
178 }