2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.mdsal.binding.java.api.generator
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.binding.lib.contract.Naming.AUGMENTATION_FIELD
13 import static org.opendaylight.yangtools.binding.lib.contract.Naming.BINDING_EQUALS_NAME
14 import static org.opendaylight.yangtools.binding.lib.contract.Naming.BINDING_HASHCODE_NAME
15 import static org.opendaylight.yangtools.binding.lib.contract.Naming.BINDING_TO_STRING_NAME
16 import static org.opendaylight.yangtools.binding.lib.contract.Naming.BUILDER_SUFFIX
17 import static org.opendaylight.yangtools.binding.lib.contract.Naming.KEY_AWARE_KEY_NAME
18 import static org.opendaylight.yangtools.binding.lib.contract.Naming.NONNULL_PREFIX
20 import java.util.Collection
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.binding.lib.AbstractAugmentable
32 class BuilderImplTemplate extends AbstractBuilderTemplate {
33 val BuilderTemplate builder;
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
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»>
48 implements «impIface» {
50 «generateFields(true)»
52 «generateCopyConstructor(builder.type, type)»
56 «generateNonnullGetters()»
66 override generateDeprecatedAnnotation(AnnotationType ann) {
67 return generateAnnotation(ann)
70 def private generateGetters() '''
72 @«OVERRIDE.importedName»
73 public «keyType.importedName» «KEY_AWARE_KEY_NAME»() {
78 «IF !properties.empty»
79 «FOR field : properties SEPARATOR '\n'»
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»
97 private static def Optional<MethodSignature> findGetter(GeneratedType implType, String getterName) {
98 val getter = getterByName(implType.nonDefaultMethods, getterName);
99 if (getter.isPresent) {
102 for (ifc : implType.implements) {
103 if (ifc instanceof GeneratedType) {
104 val getterImpl = findGetter(ifc, getterName)
105 if (getterImpl.isPresent) {
110 return Optional.empty
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();
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());
133 def private nonnullMethodName(GeneratedProperty field) {
134 return '''«NONNULL_PREFIX»«field.name.toFirstUpper»'''
137 package def findGetter(String getterName) {
138 val ownGetter = getterByName(type.nonDefaultMethods, getterName);
139 if (ownGetter.isPresent) {
140 return ownGetter.orElseThrow
142 for (ifc : type.implements) {
143 if (ifc instanceof GeneratedType) {
144 val getter = findGetter(ifc, getterName)
145 if (getter.isPresent) {
146 return (getter.orElseThrow)
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));
156 * Template method which generates the method <code>hashCode()</code>.
158 * @return string with the <code>hashCode()</code> method definition in JAVA format
160 def protected generateHashCode() '''
161 «IF !properties.empty || augmentType !== null»
162 private int hash = 0;
163 private volatile boolean hashValid = false;
165 @«OVERRIDE.importedName»
166 public int hashCode() {
171 final int result = «targetType.importedName».«BINDING_HASHCODE_NAME»(this);
180 * Template method which generates the method <code>equals()</code>.
182 * @return string with the <code>equals()</code> method definition in JAVA format
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);
194 * Template method which generates the method <code>toString()</code>.
196 * @return string with the <code>toString()</code> method definition in JAVA format
198 def protected generateToString() '''
199 @«OVERRIDE.importedName»
200 public «STRING.importedName» toString() {
201 return «targetType.importedName».«BINDING_TO_STRING_NAME»(this);
205 override protected generateCopyKeys(List<GeneratedProperty> keyProps) '''
206 if (base.«KEY_AWARE_KEY_NAME»() != null) {
207 this.key = base.«KEY_AWARE_KEY_NAME»();
209 this.key = new «keyType.importedName»(«FOR keyProp : keyProps SEPARATOR ", "»base.«keyProp.getterMethodName»()«ENDFOR»);
211 «FOR field : keyProps»
212 this.«field.fieldName» = key.«field.getterMethodName»();
216 override protected CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props) '''
218 «IF field.mechanics === ValueMechanics.NULLIFY_EMPTY»
219 this.«field.fieldName» = «CODEHELPERS.importedName».emptyToNull(base.«field.getterName»());
221 this.«field.fieldName» = base.«field.getterName»();
226 override protected generateCopyAugmentation(Type implType) '''
227 super(base.«AUGMENTATION_FIELD»);