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