*/
package org.opendaylight.mdsal.binding.java.api.generator
+import static org.opendaylight.mdsal.binding.model.ri.Types.STRING;
import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTATION_FIELD
-import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTABLE_AUGMENTATION_NAME
-import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_EQUALS_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_HASHCODE_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_TO_STRING_NAME
+import java.util.Collection
import java.util.List
-import java.util.Map
-import java.util.Objects
+import java.util.Optional
+import org.opendaylight.mdsal.binding.model.api.AnnotationType
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
import org.opendaylight.mdsal.binding.model.api.GeneratedType
+import org.opendaylight.mdsal.binding.model.api.MethodSignature
+import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics
import org.opendaylight.mdsal.binding.model.api.Type
+import org.opendaylight.mdsal.binding.model.ri.Types
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
import org.opendaylight.yangtools.yang.binding.AbstractAugmentable
-import org.opendaylight.yangtools.yang.binding.DataObject
class BuilderImplTemplate extends AbstractBuilderTemplate {
- val Type builderType;
+ val BuilderTemplate builder;
new(BuilderTemplate builder, GeneratedType type) {
super(builder.javaType.getEnclosedType(type.identifier), type, builder.targetType, builder.properties,
builder.augmentType, builder.keyType)
- this.builderType = builder.type
+ this.builder = builder
}
override body() '''
+ «targetType.annotations.generateDeprecatedAnnotation»
private static final class «type.name»
«val impIface = targetType.importedName»
«IF augmentType !== null»
«generateFields(true)»
- «generateCopyConstructor(builderType, type)»
+ «generateCopyConstructor(builder.type, type)»
- «generateGetters(true)»
+ «generateGetters()»
«generateHashCode()»
«generateEquals()»
- «generateToString(properties)»
+ «generateToString()»
}
'''
+ override generateDeprecatedAnnotation(AnnotationType ann) {
+ return generateAnnotation(ann)
+ }
+
+ def private generateGetters() '''
+ «IF keyType !== null»
+ @«OVERRIDE.importedName»
+ public «keyType.importedName» «BindingMapping.IDENTIFIABLE_KEY_NAME»() {
+ return key;
+ }
+
+ «ENDIF»
+ «IF !properties.empty»
+ «FOR field : properties SEPARATOR '\n'»
+ «field.getterMethod»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ private static def Optional<MethodSignature> findGetter(GeneratedType implType, String getterName) {
+ val getter = getterByName(implType.nonDefaultMethods, getterName);
+ if (getter.isPresent) {
+ return getter;
+ }
+ for (ifc : implType.implements) {
+ if (ifc instanceof GeneratedType) {
+ val getterImpl = findGetter(ifc, getterName)
+ if (getterImpl.isPresent) {
+ return (getterImpl)
+ }
+ }
+ }
+ return Optional.empty
+ }
+
+ override getterMethod(GeneratedProperty field) '''
+ @«OVERRIDE.importedName»
+ public «field.returnType.importedName» «field.getterMethodName»() {
+ «val fieldName = field.fieldName»
+ «IF field.returnType.name.endsWith("[]")»
+ return «fieldName» == null ? null : «fieldName».clone();
+ «ELSE»
+ return «fieldName»;
+ «ENDIF»
+ }
+ '''
+
+ package def findGetter(String getterName) {
+ val ownGetter = getterByName(type.nonDefaultMethods, getterName);
+ if (ownGetter.isPresent) {
+ return ownGetter.get;
+ }
+ for (ifc : type.implements) {
+ if (ifc instanceof GeneratedType) {
+ val getter = findGetter(ifc, getterName)
+ if (getter.isPresent) {
+ return (getter.get)
+ }
+ }
+ }
+ throw new IllegalStateException(
+ String.format("%s should be present in %s type or in one of its ancestors as getter",
+ getterName.propertyNameFromGetter, type));
+ }
+
/**
* Template method which generates the method <code>hashCode()</code>.
*
private int hash = 0;
private volatile boolean hashValid = false;
- @«Override.importedName»
+ @«OVERRIDE.importedName»
public int hashCode() {
if (hashValid) {
return hash;
}
- «hashCodeResult(properties)»
- «IF augmentType !== null»
- result = prime * result + «Objects.importedName».hashCode(augmentations());
- «ENDIF»
-
+ final int result = «targetType.importedName».«BINDING_HASHCODE_NAME»(this);
hash = result;
hashValid = true;
return result;
*/
def protected generateEquals() '''
«IF !properties.empty || augmentType !== null»
- @«Override.importedName»
- public boolean equals(«Object.importedName» obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof «DataObject.importedName»)) {
- return false;
- }
- if (!«targetType.importedName».class.equals(((«DataObject.importedName»)obj).«DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME»())) {
- return false;
- }
- «targetType.importedName» other = («targetType.importedName»)obj;
- «FOR property : properties»
- «val fieldName = property.fieldName»
- if (!«property.importedUtilClass».equals(«fieldName», other.«property.getterMethodName»())) {
- return false;
- }
- «ENDFOR»
- «IF augmentType !== null»
- if (getClass() == obj.getClass()) {
- // Simple case: we are comparing against self
- «type.name» otherImpl = («type.name») obj;
- if (!«Objects.importedName».equals(augmentations(), otherImpl.augmentations())) {
- return false;
- }
- } else {
- // Hard case: compare our augments with presence there...
- for («Map.importedName».Entry<«Class.importedName»<? extends «augmentType.importedName»>, «augmentType.importedName»> e : augmentations().entrySet()) {
- if (!e.getValue().equals(other.«AUGMENTABLE_AUGMENTATION_NAME»(e.getKey()))) {
- return false;
- }
- }
- // .. and give the other one the chance to do the same
- if (!obj.equals(this)) {
- return false;
- }
- }
- «ENDIF»
- return true;
+ @«OVERRIDE.importedName»
+ public boolean equals(«Types.objectType().importedName» obj) {
+ return «targetType.importedName».«BINDING_EQUALS_NAME»(this, obj);
}
«ENDIF»
'''
+ /**
+ * Template method which generates the method <code>toString()</code>.
+ *
+ * @return string with the <code>toString()</code> method definition in JAVA format
+ */
+ def protected generateToString() '''
+ @«OVERRIDE.importedName»
+ public «STRING.importedName» toString() {
+ return «targetType.importedName».«BINDING_TO_STRING_NAME»(this);
+ }
+ '''
+
override protected generateCopyKeys(List<GeneratedProperty> keyProps) '''
if (base.«BindingMapping.IDENTIFIABLE_KEY_NAME»() != null) {
this.key = base.«BindingMapping.IDENTIFIABLE_KEY_NAME»();
«ENDFOR»
'''
+ override protected CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props) '''
+ «FOR field : props»
+ «IF field.mechanics === ValueMechanics.NULLIFY_EMPTY»
+ this.«field.fieldName» = «CODEHELPERS.importedName».emptyToNull(base.«field.getterName»());
+ «ELSE»
+ this.«field.fieldName» = base.«field.getterName»();
+ «ENDIF»
+ «ENDFOR»
+ '''
+
override protected generateCopyAugmentation(Type implType) '''
super(base.«AUGMENTATION_FIELD»);
'''