Handling identity ref type 99/61499/2
authorVidyashree Rama <vidyashree.rama@huawei.com>
Tue, 21 Aug 2018 08:17:16 +0000 (13:47 +0530)
committerVidyashree Rama <vidyashree.rama@huawei.com>
Tue, 21 Aug 2018 09:26:05 +0000 (14:56 +0530)
Handling identity ref type in properties node serializer

Issue-ID: CCSDK-378

Change-Id: Ie74088a5e2449c09f9712048f1856990b81d05e7
Signed-off-by: Vidyashree Rama <vidyashree.rama@huawei.com>
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java
restconf-client/provider/src/test/resources/yang/identity-test.yang [new file with mode: 0644]
restconf-client/provider/src/test/resources/yang/identity-types-second.yang [new file with mode: 0644]
restconf-client/provider/src/test/resources/yang/identity-types.yang [new file with mode: 0644]

index 146e581..20b06d0 100644 (file)
@@ -34,6 +34,7 @@ import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPrope
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNamespace;
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNodeType;
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getValueNamespace;
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
@@ -121,13 +122,16 @@ public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<Sche
                 break;
             case SINGLE_INSTANCE_LEAF_NODE:
                 node = node.addChild(localName, ns, SINGLE_INSTANCE_LEAF_NODE,
-                                     value, null, schema);
+                                     value, getValueNamespace(value, schemaCtx()),
+                                     schema);
                 node = node.endNode();
                 curSchema = ((SchemaNode) node.appInfo());
                 break;
             case MULTI_INSTANCE_LEAF_NODE:
                 node = node.addChild(getIndex(name), localName, ns,
-                                     MULTI_INSTANCE_LEAF_NODE, value, null, schema);
+                                     MULTI_INSTANCE_LEAF_NODE, value,
+                                     getValueNamespace(value, schemaCtx()),
+                                     schema);
                 node = node.endNode();
                 curSchema = ((SchemaNode) node.appInfo());
                 break;
index fb57d63..5b4755e 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
 import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils;
+import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
@@ -36,6 +39,8 @@ import java.util.Deque;
 import java.util.Iterator;
 import java.util.Optional;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Represents utilities for properties node tree.
  */
@@ -294,4 +299,55 @@ public final class MdsalPropertiesNodeUtils {
     public static String getRevision(Optional<Revision> r) {
         return (r.isPresent()) ? r.get().toString() : null;
     }
+
+    /**
+     * Returns value namespace for leaf value.
+     *
+     * @param value value of the leaf
+     * @param ctx schema context
+     * @return value namespace
+     * @throws SvcLogicException if identity/module could not be found
+     */
+    static Namespace getValueNamespace(String value,
+                                              SchemaContext ctx)
+            throws SvcLogicException {
+        String prefix = getPrefixFromValue(value);
+        if (prefix == null) {
+            return null;
+        }
+
+        IdentitySchemaNode id = IdentityCodecUtil.parseIdentity(value,
+                                                                ctx,
+                                                                prefixToModule -> {
+            final Iterator<Module> modules = ctx.findModules(prefix).iterator();
+            checkArgument(modules.hasNext(), "Could not find " +
+                                  "module %s", prefix);
+            return modules.next().getQNameModule();
+        });
+
+        if (id == null) {
+            throw new SvcLogicException("Could not find identity");
+        }
+
+        return getModuleNamespace(id.getQName(), ctx);
+    }
+
+    private static String getPrefixFromValue(String value) {
+        int lastIndexOfColon = value.lastIndexOf(":");
+        if (lastIndexOfColon != -1) {
+            return value.substring(0, lastIndexOfColon);
+        }
+        return null;
+    }
+
+    private static Namespace getModuleNamespace(QName qName, SchemaContext ctx)
+            throws SvcLogicException {
+        Optional<Module> module = ctx.findModule(qName.getModule());
+        if (!module.isPresent()) {
+            throw new SvcLogicException("Could not find module node");
+        }
+        Module m = module.get();
+        return new Namespace(m.getName(), m.getQNameModule().getNamespace(),
+                             getRevision(m.getRevision()));
+    }
 }
index fddfe2d..dc0da6f 100644 (file)
@@ -1071,6 +1071,60 @@ public final class PropertiesSerializerTest {
         assertThat(node.uri(), is("test-yang:cont18.leaf40"));
     }
 
+    @Test
+    public void testIdentityRef() throws SvcLogicException {
+        String uri = "identity-test:test";
+        Map<String, String> params = new HashMap<>();
+        params.put("identity-test:test.con1.interface", "identity-types:physical");
+        params.put("identity-test:test.con1.interfaces.int-list[0].iden", "identity-test:Giga");
+        params.put("identity-test:test.con1.interfaces.int-list[0].available.ll[0]", "identity-types:Loopback");
+        params.put("identity-test:test.con1.interfaces.int-list[0].available.leaf1", "identity-types-second:Ethernet");
+        params.put("identity-test:test.con1.interfaces.int-list[0].available.leaf2", "identity-types-second:iden2");
+        InstanceIdentifierContext<?> iCtx = ParserIdentifier
+                .toInstanceIdentifier(uri, context, null);
+
+        PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+                iCtx.getSchemaNode(), context, uri);
+        PropertiesNode node = ser.encode(params);
+        Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+        assertThat(childNodes.containsKey("con1"), is(true));
+        node = childNodes.get("con1");
+        assertThat(node.uri(), is("identity-test:test.con1"));
+        LeafNode l = ((LeafNode) ((SingleInstanceNode) node).children().get("interface"));
+        assertThat(l.uri(), is("identity-test:test.con1.interface"));
+        assertThat(l.valueNs().moduleName(), is("identity-types"));
+        assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+        // identity type inside union
+        node = ((SingleInstanceNode) ((SingleInstanceNode) node).children().get("interfaces"));
+        node = ((ListHolderNode) ((SingleInstanceNode) node).children().get("int-list"));
+        node = ((MultiInstanceNode) ((ListHolderNode) node).children().get("0"));
+        l = ((LeafNode) ((MultiInstanceNode) node).children().get("iden"));
+        assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].iden"));
+        assertThat(l.valueNs().moduleName(), is("identity-test"));
+        assertThat(l.valueNs().moduleNs().toString(), is("identity:ns:test:json:ser"));
+
+        // leaf-list test
+        node = (SingleInstanceNode) ((MultiInstanceNode) node).children().get("available");
+        LeafListHolderNode holder = (LeafListHolderNode) ((SingleInstanceNode) node).children().get("ll");
+        l = ((LeafNode) holder.children().get("0"));
+        assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.ll[0]"));
+        assertThat(l.valueNs().moduleName(), is("identity-types"));
+        assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+        // leaf-ref test
+        l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf1"));
+        assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf1"));
+        assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+        assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+
+        // list of base identity test
+        l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf2"));
+        assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf2"));
+        assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+        assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+    }
+
     public static SchemaContext compileYangFile() throws FileNotFoundException {
         String path = PropertiesSerializerTest.class.getResource("/yang").getPath();
         File dir = new File(path);
diff --git a/restconf-client/provider/src/test/resources/yang/identity-test.yang b/restconf-client/provider/src/test/resources/yang/identity-test.yang
new file mode 100644 (file)
index 0000000..81d3f0a
--- /dev/null
@@ -0,0 +1,77 @@
+module identity-test {
+    yang-version 1.1;
+    namespace "identity:ns:test:json:ser";
+    prefix "id";
+
+    import identity-types {
+        prefix "type";
+    }
+
+    import identity-types-second {
+        prefix "sec";
+    }
+
+    revision "2013-07-15";
+
+    identity optical {
+        base type:int-type;
+    }
+
+    identity Giga {
+        base type:physical;
+    }
+
+    typedef available {
+        type identityref {
+            base "type:physical";
+        }
+    }
+
+    typedef typed{
+        type union {
+            type int32;
+            type int8;
+            type identityref {
+                base type:int-type;
+            }
+        }
+    }
+
+    container test {
+        leaf l {
+            type string;
+        }
+        container con1 {
+            leaf interface {
+                type identityref {
+                    base "type:int-type";
+                }
+            }
+            container interfaces {
+                list int-list {
+                    key "iden";
+                    leaf iden {
+                        type "id:typed";
+                    }
+                    container available {
+                        leaf-list ll {
+                            type available;
+                        }
+                        leaf leaf1 {
+                          type leafref {
+                              path "../../iden";
+                          }
+                        }
+
+                        leaf leaf2 {
+                           type identityref {
+                                base type:int-type;
+                                base sec:iden1;
+                           }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/restconf-client/provider/src/test/resources/yang/identity-types-second.yang b/restconf-client/provider/src/test/resources/yang/identity-types-second.yang
new file mode 100644 (file)
index 0000000..ad752de
--- /dev/null
@@ -0,0 +1,25 @@
+module  identity-types-second{
+    yang-version 1;
+    namespace "identity:list:second:ns:test:json:ser";
+    prefix "sec";
+
+    import identity-types {
+        prefix "type";
+    }
+
+    revision "2013-07-15";
+
+    identity virtual {
+        base type:int-type;
+    }
+
+    identity Ethernet {
+        base type:physical;
+    }
+
+    identity iden1;
+
+    identity iden2 {
+        base iden1;
+    }
+}
diff --git a/restconf-client/provider/src/test/resources/yang/identity-types.yang b/restconf-client/provider/src/test/resources/yang/identity-types.yang
new file mode 100644 (file)
index 0000000..25c8fa5
--- /dev/null
@@ -0,0 +1,17 @@
+module identity-types {
+    yang-version 1;
+    namespace "identity:list:ns:test:json:ser";
+    prefix "type";
+    revision "2013-07-15";
+
+    identity int-type {
+    }
+
+    identity physical {
+        base int-type;
+    }
+
+    identity Loopback {
+        base physical;
+    }
+}