Specialize relative leafref types during instantiation
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / BuilderImplTemplate.xtend
index 650d15cf809f365fddf0744c6379537ad7b9823e..25c07c25c666e102e1b3d418d3a50001970e8af1 100644 (file)
@@ -7,32 +7,32 @@
  */
 package org.opendaylight.mdsal.binding.java.api.generator
 
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT
 import static org.opendaylight.mdsal.binding.model.util.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.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 static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
 
 import java.util.Collection
 import java.util.List
+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.util.Types
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
 import org.opendaylight.yangtools.yang.binding.AbstractAugmentable
-import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics
 
 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() '''
@@ -46,9 +46,9 @@ class BuilderImplTemplate extends AbstractBuilderTemplate {
 
             «generateFields(true)»
 
-            «generateCopyConstructor(builderType, type)»
+            «generateCopyConstructor(builder.type, type)»
 
-            «generateGetters(true
+            «generateGetters()»
 
             «generateHashCode()»
 
@@ -62,6 +62,67 @@ class BuilderImplTemplate extends AbstractBuilderTemplate {
         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>.
      *
@@ -95,43 +156,7 @@ class BuilderImplTemplate extends AbstractBuilderTemplate {
         «IF !properties.empty || augmentType !== null»
             @«OVERRIDE.importedName»
             public boolean equals(«Types.objectType().importedName» obj) {
-                if (this == obj) {
-                    return true;
-                }
-                if (!(obj instanceof «DATA_OBJECT.importedName»)) {
-                    return false;
-                }
-                if (!«targetType.importedName».class.equals(((«DATA_OBJECT.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.getterName»())) {
-                        return false;
-                    }
-                «ENDFOR»
-                «IF augmentType !== null»
-                    if (getClass() == obj.getClass()) {
-                        // Simple case: we are comparing against self
-                        «type.name» otherImpl = («type.name») obj;
-                        if (!«JU_OBJECTS.importedName».equals(augmentations(), otherImpl.augmentations())) {
-                            return false;
-                        }
-                    } else {
-                        // Hard case: compare our augments with presence there...
-                        for («JU_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;
+                return «targetType.importedName».«BINDING_EQUALS_NAME»(this, obj);
             }
         «ENDIF»
     '''