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