MDSAL-17: Binding V2 - Simplify InstanceIdentifer creation 10/67910/16
authorJie Han <han.jie@zte.com.cn>
Mon, 5 Feb 2018 06:49:38 +0000 (14:49 +0800)
committerRobert Varga <nite@hq.sk>
Mon, 3 Sep 2018 08:12:24 +0000 (08:12 +0000)
- Add a static method getInstanceIdentifier to generated interface
  of datastore nodes:

  - If there are list items, just toke its key as inputs, like:
    getInstanceIdentifier(key1, key2,...),

  -Or it would simply be getInstanceIdentifier().

- For choice/case's children data nodes, II does not reference
  choice or case but through them.

- Add unit tests.

Change-Id: Iea592557668fd7a8ab8e6874caaac7b9e834a859
Signed-off-by: Jie Han <han.jie@zte.com.cn>
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/InstanceIdentifierTest.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java [changed mode: 0644->0755]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/interfaceTemplate.scala.txt [changed mode: 0644->0755]

diff --git a/binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/InstanceIdentifierTest.java b/binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/InstanceIdentifierTest.java
new file mode 100644 (file)
index 0000000..c8febc9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.javav2.dom.codec.impl;
+
+import static org.junit.Assert.assertTrue;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.impl.StreamWriterGenerator;
+import org.opendaylight.mdsal.binding.javav2.runtime.javassist.JavassistUtils;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.gen.javav2.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.data.ChoiceContainer;
+import org.opendaylight.mdsal.gen.javav2.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.data.Top;
+import org.opendaylight.mdsal.gen.javav2.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.data.choice_container.identifier.extended.ExtendedId;
+import org.opendaylight.mdsal.gen.javav2.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.data.top.TopLevelList;
+import org.opendaylight.mdsal.gen.javav2.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.key.top.top_level_list.TopLevelListKey;
+
+public class InstanceIdentifierTest extends AbstractBindingRuntimeTest {
+    private static final InstanceIdentifier<Top> BA_TOP = InstanceIdentifier.builder(Top.class).build();
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<ExtendedId> BA_EXTEND_ID = InstanceIdentifier.builder(ChoiceContainer.class)
+        .child(ExtendedId.class).build();
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testInstanceIdentifierNormal() {
+        assertTrue(Top.getInstanceIdentifier().equals(BA_TOP));
+    }
+
+    @Test
+    public void testInstanceIdentifierOfList() {
+        assertTrue(TopLevelList.getInstanceIdentifier(TOP_FOO_KEY).equals(BA_TOP_LEVEL_LIST));
+    }
+
+    @Test
+    public void testInstanceIdentifierOfCase() {
+        assertTrue(ExtendedId.getInstanceIdentifier().equals(BA_EXTEND_ID));
+    }
+
+}
index 21f578da23ca6a79e4358402fd2839f298b9771b..64d54c48a67c32f6d37b73ea861db97c73d0dfc4 100755 (executable)
@@ -439,11 +439,20 @@ final class GenHelperUtil {
         augTypeBuilder.setBindingNamespaceType(namespaceType);
         annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
 
+        //If target is case node then pass down parent type (the closest ancestor) to children data nodes.
+        final GeneratedTypeBuilder childOf;
+        if (targetNode instanceof CaseSchemaNode) {
+            childOf = (GeneratedTypeBuilder) targetTypeBuilder.getParentTypeForBuilder();
+        } else {
+            augTypeBuilder.setParentTypeForBuilder(targetTypeBuilder);
+            childOf = targetTypeBuilder;
+        }
+
         //produces getters for augTypeBuilder eventually
         for (AugmentationSchemaNode aug : schemaPathAugmentListEntry) {
             //apply all uses
             addImplementedInterfaceFromUses(aug, augTypeBuilder, genCtx);
-            augSchemaNodeToMethods(module, BindingMapping.getRootPackageName(module), augTypeBuilder, augTypeBuilder,
+            augSchemaNodeToMethods(module, BindingMapping.getRootPackageName(module), augTypeBuilder, childOf,
                 aug.getChildNodes(), genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders,
                 targetTypeBuilder.getBindingNamespaceType());
         }
old mode 100644 (file)
new mode 100755 (executable)
index 0b11d40..470632b
@@ -9,19 +9,29 @@
 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
 
 import com.google.common.base.Preconditions;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
+import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
+import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.constantsTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.enumTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.interfaceTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
 import org.opendaylight.mdsal.binding.javav2.model.api.AnnotationType;
-import org.opendaylight.mdsal.binding.javav2.model.api.Constant;
 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.yangtools.yang.common.QName;
 
 public class InterfaceRenderer extends BaseRenderer {
@@ -76,6 +86,8 @@ public class InterfaceRenderer extends BaseRenderer {
         final String generatedConstants = constantsTemplate.render(getType(), getImportedNames(),
             this::importedName, true).body();
 
+        final Entry<String, String> identifier = generateInstanceIdentifier();
+
         final List<String> innerClasses = new ArrayList<>(getType().getEnclosedTypes().size());
         for (GeneratedType innerClass : getType().getEnclosedTypes()) {
             if (innerClass instanceof GeneratedTransferObject) {
@@ -93,7 +105,7 @@ public class InterfaceRenderer extends BaseRenderer {
         final String generatedInnerClasses = String.join("\n", innerClasses);
 
         return interfaceTemplate.render(getType(), enums, mainAnnotations, methodList, generatedImports,
-                generatedConstants, generatedInnerClasses).body();
+                generatedConstants, generatedInnerClasses, identifier.getKey(), identifier.getValue()).body();
     }
 
     private static boolean isAccessor(final MethodSignature maybeGetter) {
@@ -131,6 +143,62 @@ public class InterfaceRenderer extends BaseRenderer {
         return sb1.toString();
     }
 
+    /**
+     * Generate default method getInstanceIdentifier.
+     * @return  string pair of instance identifier and key parameters
+     */
+    private Entry<String, String> generateInstanceIdentifier() {
+        //Only tree data nodes need to generate the method.
+        if (null == getType().getBindingNamespaceType() ||
+            !BindingNamespaceType.isTreeData(getType().getBindingNamespaceType()) ||
+            !getType().getImplements().contains(BindingTypes.TREE_CHILD_NODE) ) {
+            return new SimpleEntry<>(null, null);
+        }
+
+        final Deque<GeneratedType> dataPath = new ArrayDeque<>();
+        GeneratedType type = getType();
+        GeneratedTypeBuilder parentTypeBuilder;
+
+        while (type != null) {
+            dataPath.push(type);
+            importedName(type);
+            parentTypeBuilder = (GeneratedTypeBuilder) type.getParentTypeForBuilder();
+            type = parentTypeBuilder != null ? parentTypeBuilder.toInstance() : null;
+        }
+
+        dataPath.pop();
+
+        final StringBuilder iiBuidler = new StringBuilder();
+        type = dataPath.pop();
+        iiBuidler.append("InstanceIdentifier.builder(").append(type.getName()).append(".class)");
+        importedName(InstanceIdentifier.class);
+        final List<String> keys = new ArrayList<>();
+        while (dataPath.peek() != null) {
+            type = dataPath.pop();
+            if (type.getImplements().contains(BindingTypes.AUGMENTATION)) {
+                iiBuidler.append(".augmentation(").append(type.getName()).append(".class)");
+            } else {
+                Optional<MethodSignature> method = type.getMethodDefinitions().stream().filter(m ->
+                    m.getName().equals("getIdentifier")).findFirst();
+                if (method.isPresent()) {
+                    importedName(method.get().getReturnType());
+                    final String keyName = method.get().getReturnType().getName();
+                    final String normalizedKeyName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(keyName,
+                        JavaIdentifier.METHOD);
+                    keys.add(new StringBuilder().append("final ").append(keyName).append(" _")
+                        .append(normalizedKeyName).toString());
+                    iiBuidler.append(".child(").append(type.getFullyQualifiedName()).append(".class, _")
+                        .append(normalizedKeyName).append(")");
+                } else {
+                    iiBuidler.append(".child(").append(type.getFullyQualifiedName()).append(".class)");
+                }
+            }
+        }
+        iiBuidler.append(".build()");
+        return new SimpleEntry<>(iiBuidler.toString(), String.join(", ", keys));
+    }
+
+
     /**
      * @param parameters list of parameters
      * @return list of parameters separated with ","
old mode 100644 (file)
new mode 100755 (executable)
index e0d53a7..f3ff1eb
@@ -8,11 +8,13 @@
 
 @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject
 @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType
+@import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTypeForBuilder
 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.formatDataForJavaDoc
 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.wrapToDocumentation
+@import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType
 
 @(genType: GeneratedType, enums: String, annotations: String, generatedMethods: String, generatedImports: String,
-generatedConstants: String, innerClasses: String)
+generatedConstants: String, innerClasses: String, getII: String, keyParams: String)
 @*
  * Template method which generate the whole body of the interface.
  *
@@ -28,5 +30,11 @@ public interface @{genType.getName}
     @{enums}
     @{generatedConstants}
     @{generatedMethods}
+
+    @if(getII != null) {
+    public static InstanceIdentifier<@{genType.getName}> getInstanceIdentifier(@{keyParams}) {
+      return @{getII};
+    }
+    }
 }
 }
\ No newline at end of file