Fixup BuilderTemplate decomposition
[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 java.util.Arrays
14 import java.util.Objects
15 import java.util.Map
16 import org.opendaylight.mdsal.binding.model.api.GeneratedType
17 import org.opendaylight.mdsal.binding.model.api.Type
18 import org.opendaylight.yangtools.yang.binding.DataObject
19
20 class BuilderImplTemplate extends AbstractBuilderTemplate {
21     val Type builderType;
22
23     new(BuilderTemplate builder, GeneratedType type) {
24         super(builder.javaType.getEnclosedType(type.identifier), type, builder.targetType, builder.properties,
25             builder.augmentType, builder.keyType)
26         this.builderType = builder.type
27     }
28
29     override body() '''
30         private static final class «type.name» implements «targetType.importedName» {
31
32             «generateFields(true)»
33
34             «generateAugmentField(true)»
35
36             «generateCopyConstructor(true, builderType, type)»
37
38             @«Override.importedName»
39             public «Class.importedName»<«targetType.importedName»> getImplementedInterface() {
40                 return «targetType.importedName».class;
41             }
42
43             «generateGetters(true)»
44
45             «generateHashCode()»
46
47             «generateEquals()»
48
49             «generateToString(properties)»
50         }
51     '''
52
53     /**
54      * Template method which generates the method <code>hashCode()</code>.
55      *
56      * @return string with the <code>hashCode()</code> method definition in JAVA format
57      */
58     def protected generateHashCode() '''
59         «IF !properties.empty || augmentType !== null»
60             private int hash = 0;
61             private volatile boolean hashValid = false;
62
63             @«Override.importedName»
64             public int hashCode() {
65                 if (hashValid) {
66                     return hash;
67                 }
68
69                 final int prime = 31;
70                 int result = 1;
71                 «FOR property : properties»
72                     «IF property.returnType.name.contains("[")»
73                     result = prime * result + «Arrays.importedName».hashCode(«property.fieldName»);
74                     «ELSE»
75                     result = prime * result + «Objects.importedName».hashCode(«property.fieldName»);
76                     «ENDIF»
77                 «ENDFOR»
78                 «IF augmentType !== null»
79                     result = prime * result + «Objects.importedName».hashCode(«AUGMENTATION_FIELD»);
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).getImplementedInterface())) {
105                     return false;
106                 }
107                 «targetType.importedName» other = («targetType.importedName»)obj;
108                 «FOR property : properties»
109                     «val fieldName = property.fieldName»
110                     «IF property.returnType.name.contains("[")»
111                     if (!«Arrays.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
112                     «ELSE»
113                     if (!«Objects.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
114                     «ENDIF»
115                         return false;
116                     }
117                 «ENDFOR»
118                 «IF augmentType !== null»
119                     if (getClass() == obj.getClass()) {
120                         // Simple case: we are comparing against self
121                         «type.name» otherImpl = («type.name») obj;
122                         if (!«Objects.importedName».equals(«AUGMENTATION_FIELD», otherImpl.«AUGMENTATION_FIELD»)) {
123                             return false;
124                         }
125                     } else {
126                         // Hard case: compare our augments with presence there...
127                         for («Map.importedName».Entry<«Class.importedName»<? extends «augmentType.importedName»>, «augmentType.importedName»> e : «AUGMENTATION_FIELD».entrySet()) {
128                             if (!e.getValue().equals(other.«AUGMENTABLE_AUGMENTATION_NAME»(e.getKey()))) {
129                                 return false;
130                             }
131                         }
132                         // .. and give the other one the chance to do the same
133                         if (!obj.equals(this)) {
134                             return false;
135                         }
136                     }
137                 «ENDIF»
138                 return true;
139             }
140         «ENDIF»
141     '''
142 }