Reduce use of BaseTemplate.getterMethodName()
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / BuilderImplTemplate.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.BindingTypes.DATA_OBJECT
11 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTATION_FIELD
12 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTABLE_AUGMENTATION_NAME
13 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
14
15 import java.util.Collection
16 import java.util.List
17 import org.opendaylight.mdsal.binding.model.api.AnnotationType
18 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
19 import org.opendaylight.mdsal.binding.model.api.GeneratedType
20 import org.opendaylight.mdsal.binding.model.api.Type
21 import org.opendaylight.mdsal.binding.model.util.Types
22 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
23 import org.opendaylight.yangtools.yang.binding.AbstractAugmentable
24 import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics
25
26 class BuilderImplTemplate extends AbstractBuilderTemplate {
27     val Type builderType;
28
29     new(BuilderTemplate builder, GeneratedType type) {
30         super(builder.javaType.getEnclosedType(type.identifier), type, builder.targetType, builder.properties,
31             builder.augmentType, builder.keyType)
32         this.builderType = builder.type
33     }
34
35     override body() '''
36         «targetType.annotations.generateDeprecatedAnnotation»
37         private static final class «type.name»
38             «val impIface = targetType.importedName»
39             «IF augmentType !== null»
40                 extends «AbstractAugmentable.importedName»<«impIface»>
41             «ENDIF»
42             implements «impIface» {
43
44             «generateFields(true)»
45
46             «generateCopyConstructor(builderType, type)»
47
48             «generateGetters(true)»
49
50             «generateHashCode()»
51
52             «generateEquals()»
53
54             «generateToString(properties)»
55         }
56     '''
57
58     override generateDeprecatedAnnotation(AnnotationType ann) {
59         return generateAnnotation(ann)
60     }
61
62     /**
63      * Template method which generates the method <code>hashCode()</code>.
64      *
65      * @return string with the <code>hashCode()</code> method definition in JAVA format
66      */
67     def protected generateHashCode() '''
68         «IF !properties.empty || augmentType !== null»
69             private int hash = 0;
70             private volatile boolean hashValid = false;
71
72             @«OVERRIDE.importedName»
73             public int hashCode() {
74                 if (hashValid) {
75                     return hash;
76                 }
77
78                 «hashCodeResult(properties)»
79                 «IF augmentType !== null»
80                     result = prime * result + «JU_OBJECTS.importedName».hashCode(augmentations());
81                 «ENDIF»
82
83                 hash = result;
84                 hashValid = true;
85                 return result;
86             }
87         «ENDIF»
88     '''
89
90     /**
91      * Template method which generates the method <code>equals()</code>.
92      *
93      * @return string with the <code>equals()</code> method definition in JAVA format
94      */
95     def protected generateEquals() '''
96         «IF !properties.empty || augmentType !== null»
97             @«OVERRIDE.importedName»
98             public boolean equals(«Types.objectType().importedName» obj) {
99                 if (this == obj) {
100                     return true;
101                 }
102                 if (!(obj instanceof «DATA_OBJECT.importedName»)) {
103                     return false;
104                 }
105                 if (!«targetType.importedName».class.equals(((«DATA_OBJECT.importedName»)obj).«DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME»())) {
106                     return false;
107                 }
108                 «targetType.importedName» other = («targetType.importedName»)obj;
109                 «FOR property : properties»
110                     «val fieldName = property.fieldName»
111                     if (!«property.importedUtilClass».equals(«fieldName», other.«property.getterName»())) {
112                         return false;
113                     }
114                 «ENDFOR»
115                 «IF augmentType !== null»
116                     if (getClass() == obj.getClass()) {
117                         // Simple case: we are comparing against self
118                         «type.name» otherImpl = («type.name») obj;
119                         if (!«JU_OBJECTS.importedName».equals(augmentations(), otherImpl.augmentations())) {
120                             return false;
121                         }
122                     } else {
123                         // Hard case: compare our augments with presence there...
124                         for («JU_MAP.importedName».Entry<«CLASS.importedName»<? extends «augmentType.importedName»>, «augmentType.importedName»> e : augmentations().entrySet()) {
125                             if (!e.getValue().equals(other.«AUGMENTABLE_AUGMENTATION_NAME»(e.getKey()))) {
126                                 return false;
127                             }
128                         }
129                         // .. and give the other one the chance to do the same
130                         if (!obj.equals(this)) {
131                             return false;
132                         }
133                     }
134                 «ENDIF»
135                 return true;
136             }
137         «ENDIF»
138     '''
139
140     override protected generateCopyKeys(List<GeneratedProperty> keyProps) '''
141         if (base.«BindingMapping.IDENTIFIABLE_KEY_NAME»() != null) {
142             this.key = base.«BindingMapping.IDENTIFIABLE_KEY_NAME»();
143         } else {
144             this.key = new «keyType.importedName»(«FOR keyProp : keyProps SEPARATOR ", "»base.«keyProp.getterMethodName»()«ENDFOR»);
145         }
146         «FOR field : keyProps»
147             this.«field.fieldName» = key.«field.getterMethodName»();
148         «ENDFOR»
149     '''
150
151     override protected CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props) '''
152         «FOR field : props»
153             «IF field.mechanics === ValueMechanics.NULLIFY_EMPTY»
154                 this.«field.fieldName» = «CODEHELPERS.importedName».emptyToNull(base.«field.getterName»());
155             «ELSE»
156                 this.«field.fieldName» = base.«field.getterName»();
157             «ENDIF»
158         «ENDFOR»
159     '''
160
161     override protected generateCopyAugmentation(Type implType) '''
162         super(base.«AUGMENTATION_FIELD»);
163     '''
164 }