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