Migrate Optional.get() callers
[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 extension org.opendaylight.mdsal.binding.java.api.generator.GeneratorUtil.isNonPresenceContainer;
11 import static org.opendaylight.mdsal.binding.model.ri.Types.STRING;
12 import static org.opendaylight.yangtools.yang.binding.contract.Naming.AUGMENTATION_FIELD
13 import static org.opendaylight.yangtools.yang.binding.contract.Naming.BINDING_EQUALS_NAME
14 import static org.opendaylight.yangtools.yang.binding.contract.Naming.BINDING_HASHCODE_NAME
15 import static org.opendaylight.yangtools.yang.binding.contract.Naming.BINDING_TO_STRING_NAME
16 import static org.opendaylight.yangtools.yang.binding.contract.Naming.BUILDER_SUFFIX
17 import static org.opendaylight.yangtools.yang.binding.contract.Naming.IDENTIFIABLE_KEY_NAME
18 import static org.opendaylight.yangtools.yang.binding.contract.Naming.NONNULL_PREFIX
19
20 import java.util.Collection
21 import java.util.List
22 import java.util.Optional
23 import org.opendaylight.mdsal.binding.model.api.AnnotationType
24 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
25 import org.opendaylight.mdsal.binding.model.api.GeneratedType
26 import org.opendaylight.mdsal.binding.model.api.MethodSignature
27 import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics
28 import org.opendaylight.mdsal.binding.model.api.Type
29 import org.opendaylight.mdsal.binding.model.ri.Types
30 import org.opendaylight.yangtools.yang.binding.AbstractAugmentable
31
32 class BuilderImplTemplate extends AbstractBuilderTemplate {
33     val BuilderTemplate builder;
34
35     new(BuilderTemplate builder, GeneratedType type) {
36         super(builder.javaType.getEnclosedType(type.identifier), type, builder.targetType, builder.properties,
37             builder.augmentType, builder.keyType)
38         this.builder = builder
39     }
40
41     override body() '''
42         «targetType.annotations.generateDeprecatedAnnotation»
43         private static final class «type.name»
44             «val impIface = targetType.importedName»
45             «IF augmentType !== null»
46                 extends «AbstractAugmentable.importedName»<«impIface»>
47             «ENDIF»
48             implements «impIface» {
49
50             «generateFields(true)»
51
52             «generateCopyConstructor(builder.type, type)»
53
54             «generateGetters()»
55
56             «generateNonnullGetters()»
57
58             «generateHashCode()»
59
60             «generateEquals()»
61
62             «generateToString()»
63         }
64     '''
65
66     override generateDeprecatedAnnotation(AnnotationType ann) {
67         return generateAnnotation(ann)
68     }
69
70     def private generateGetters() '''
71         «IF keyType !== null»
72             @«OVERRIDE.importedName»
73             public «keyType.importedName» «IDENTIFIABLE_KEY_NAME»() {
74                 return key;
75             }
76
77         «ENDIF»
78         «IF !properties.empty»
79             «FOR field : properties SEPARATOR '\n'»
80                 «field.getterMethod»
81             «ENDFOR»
82         «ENDIF»
83     '''
84
85     def private generateNonnullGetters() '''
86         «IF !properties.empty»
87             «FOR field : properties SEPARATOR '\n'»
88                 «IF field.returnType instanceof GeneratedType»
89                     «IF isNonPresenceContainer(field.returnType as GeneratedType)»
90                         «field.nonNullGetterMethod»
91                     «ENDIF»
92                 «ENDIF»
93             «ENDFOR»
94         «ENDIF»
95     '''
96
97     private static def Optional<MethodSignature> findGetter(GeneratedType implType, String getterName) {
98         val getter = getterByName(implType.nonDefaultMethods, getterName);
99         if (getter.isPresent) {
100             return getter;
101         }
102         for (ifc : implType.implements) {
103             if (ifc instanceof GeneratedType) {
104                 val getterImpl = findGetter(ifc, getterName)
105                 if (getterImpl.isPresent) {
106                     return (getterImpl)
107                 }
108             }
109         }
110         return Optional.empty
111     }
112
113     override getterMethod(GeneratedProperty field) '''
114         @«OVERRIDE.importedName»
115         public «field.returnType.importedName» «field.getterMethodName»() {
116             «val fieldName = field.fieldName»
117             «IF field.returnType.name.endsWith("[]")»
118                 return «fieldName» == null ? null : «fieldName».clone();
119             «ELSE»
120                 return «fieldName»;
121             «ENDIF»
122         }
123     '''
124
125     def private nonNullGetterMethod(GeneratedProperty field) '''
126         @«OVERRIDE.importedName»
127         «val type = field.returnType»
128         public «type.importedName» «field.nonnullMethodName»() {
129             return «JU_OBJECTS.importedName».requireNonNullElse(«field.getterMethodName»(), «type.fullyQualifiedName»«BUILDER_SUFFIX».empty());
130         }
131     '''
132
133     def private nonnullMethodName(GeneratedProperty field) {
134         return '''«NONNULL_PREFIX»«field.name.toFirstUpper»'''
135     }
136
137     package def findGetter(String getterName) {
138         val ownGetter = getterByName(type.nonDefaultMethods, getterName);
139         if (ownGetter.isPresent) {
140             return ownGetter.orElseThrow
141         }
142         for (ifc : type.implements) {
143             if (ifc instanceof GeneratedType) {
144                 val getter = findGetter(ifc, getterName)
145                 if (getter.isPresent) {
146                     return (getter.orElseThrow)
147                 }
148             }
149         }
150         throw new IllegalStateException(
151                 String.format("%s should be present in %s type or in one of its ancestors as getter",
152                         getterName.propertyNameFromGetter, type));
153     }
154
155     /**
156      * Template method which generates the method <code>hashCode()</code>.
157      *
158      * @return string with the <code>hashCode()</code> method definition in JAVA format
159      */
160     def protected generateHashCode() '''
161         «IF !properties.empty || augmentType !== null»
162             private int hash = 0;
163             private volatile boolean hashValid = false;
164
165             @«OVERRIDE.importedName»
166             public int hashCode() {
167                 if (hashValid) {
168                     return hash;
169                 }
170
171                 final int result = «targetType.importedName».«BINDING_HASHCODE_NAME»(this);
172                 hash = result;
173                 hashValid = true;
174                 return result;
175             }
176         «ENDIF»
177     '''
178
179     /**
180      * Template method which generates the method <code>equals()</code>.
181      *
182      * @return string with the <code>equals()</code> method definition in JAVA format
183      */
184     def protected generateEquals() '''
185         «IF !properties.empty || augmentType !== null»
186             @«OVERRIDE.importedName»
187             public boolean equals(«Types.objectType().importedName» obj) {
188                 return «targetType.importedName».«BINDING_EQUALS_NAME»(this, obj);
189             }
190         «ENDIF»
191     '''
192
193     /**
194      * Template method which generates the method <code>toString()</code>.
195      *
196      * @return string with the <code>toString()</code> method definition in JAVA format
197      */
198     def protected generateToString() '''
199         @«OVERRIDE.importedName»
200         public «STRING.importedName» toString() {
201             return «targetType.importedName».«BINDING_TO_STRING_NAME»(this);
202         }
203     '''
204
205     override protected generateCopyKeys(List<GeneratedProperty> keyProps) '''
206         if (base.«IDENTIFIABLE_KEY_NAME»() != null) {
207             this.key = base.«IDENTIFIABLE_KEY_NAME»();
208         } else {
209             this.key = new «keyType.importedName»(«FOR keyProp : keyProps SEPARATOR ", "»base.«keyProp.getterMethodName»()«ENDFOR»);
210         }
211         «FOR field : keyProps»
212             this.«field.fieldName» = key.«field.getterMethodName»();
213         «ENDFOR»
214     '''
215
216     override protected CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props) '''
217         «FOR field : props»
218             «IF field.mechanics === ValueMechanics.NULLIFY_EMPTY»
219                 this.«field.fieldName» = «CODEHELPERS.importedName».emptyToNull(base.«field.getterName»());
220             «ELSE»
221                 this.«field.fieldName» = base.«field.getterName»();
222             «ENDIF»
223         «ENDFOR»
224     '''
225
226     override protected generateCopyAugmentation(Type implType) '''
227         super(base.«AUGMENTATION_FIELD»);
228     '''
229 }