Bug 7844 - Unable to create LeafRefContext for leafref 46/56946/5
authorPeter Kajsa <pkajsa@cisco.com>
Fri, 12 May 2017 12:10:50 +0000 (14:10 +0200)
committerRobert Varga <nite@hq.sk>
Tue, 16 May 2017 23:34:13 +0000 (23:34 +0000)
In order to get correct namespace for a prefix used in a leafref
path we need to find the module which contains definition
of leafref path and then a prefix need to be resolved based on
imports of this module.

Change-Id: Icfb599783e90e44935d5e18eea23b0ac0d86cbf0
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefContextTreeBuilder.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/leafref/Bug7844Test.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/bug7844/bar.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/bug7844/baz.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/bug7844/foo.yang [new file with mode: 0644]

index cda5be533703b329c6ffb3ceed1f4bf8d79aa607..20d2f1e267ffb008c15ed27c519a60aeab88a7da 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.leafref;
 
+import com.google.common.base.Preconditions;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -14,6 +15,7 @@ import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -128,8 +130,10 @@ class LeafRefContextTreeBuilder {
                 currentLeafRefContextBuilder.setLeafRefTargetPathString(leafRefPathString);
                 currentLeafRefContextBuilder.setReferencing(true);
 
-                final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(
-                        schemaContext, currentModule, node);
+                final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(schemaContext,
+                        Preconditions.checkNotNull(getBaseTypeModule(leafrefType),
+                                "Unable to find base module for leafref %s", node),
+                        node);
 
                 final LeafRefPath leafRefPath = leafRefPathParser.parseLeafRefPathSourceToSchemaPath(
                     new ByteArrayInputStream(leafRefPathString.getBytes(StandardCharsets.UTF_8)));
@@ -145,6 +149,19 @@ class LeafRefContextTreeBuilder {
         return currentLeafRefContextBuilder.build();
     }
 
+    private Module getBaseTypeModule(final LeafrefTypeDefinition leafrefType) {
+        /*
+         * Find the first definition of supplied leafref type and return the
+         * module which contains this definition.
+         */
+        LeafrefTypeDefinition baseLeafRefType = leafrefType;
+        while (baseLeafRefType.getBaseType() != null) {
+            baseLeafRefType = baseLeafRefType.getBaseType();
+        }
+        final QNameModule module = baseLeafRefType.getQName().getModule();
+        return schemaContext.findModuleByNamespaceAndRevision(module.getNamespace(), module.getRevision());
+    }
+
     private LeafRefContext buildLeafRefContextReferencedByTree(
             final DataSchemaNode node, final Module currentModule) throws IOException,
             LeafRefYangSyntaxErrorException {
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/leafref/Bug7844Test.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/leafref/Bug7844Test.java
new file mode 100644 (file)
index 0000000..f6e8bac
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017 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.yangtools.yang.data.impl.leafref;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import java.net.URI;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class Bug7844Test {
+    private static final String FOO_NS = "foo";
+    private static final String BAR_NS = "bar";
+    private static final String BAZ_NS = "baz";
+    private static final String REV = "1970-01-01";
+
+    @Test
+    public void test() throws Exception {
+        final SchemaContext context = YangParserTestUtils.parseYangSources("/bug7844");
+        assertNotNull(context);
+
+        final LeafRefContext leafRefContext = LeafRefContext.create(context);
+        assertNotNull(leafRefContext);
+
+        final Map<QName, LeafRefContext> referencingChilds = leafRefContext.getReferencingChilds();
+        assertEquals(7, referencingChilds.size());
+
+        final QNameModule bazQNameModule = QNameModule.create(new URI(BAZ_NS),
+                SimpleDateFormatUtil.getRevisionFormat().parse(REV));
+        final LeafRefPath expectedPathToBazTarget = LeafRefPath.create(true,
+                new QNameWithPredicateImpl(bazQNameModule, "root", ImmutableList.of()),
+                new QNameWithPredicateImpl(bazQNameModule, "target", ImmutableList.of()));
+        final LeafRefContext myLeafCtx = referencingChilds.get(foo("my-leaf"));
+        assertLeafRef(myLeafCtx, expectedPathToBazTarget);
+        assertLeafRef(referencingChilds.get(foo("my-leaf-2")), expectedPathToBazTarget);
+        assertLeafRef(referencingChilds.get(foo("bar-base-leafref")), expectedPathToBazTarget);
+        assertLeafRef(referencingChilds.get(foo("bar-base-leafref-2")), expectedPathToBazTarget);
+        assertLeafRef(referencingChilds.get(bar("my-leafref-in-bar")), expectedPathToBazTarget);
+        assertLeafRef(referencingChilds.get(bar("my-leafref-in-bar-2")), expectedPathToBazTarget);
+
+        final QNameModule barQNameModule = QNameModule.create(new URI(BAR_NS),
+                SimpleDateFormatUtil.getRevisionFormat().parse(REV));
+        final LeafRefPath expectedPathToBarTarget = LeafRefPath.create(true,
+                new QNameWithPredicateImpl(barQNameModule, "bar-target", ImmutableList.of()));
+        assertLeafRef(referencingChilds.get(foo("direct-leafref")), expectedPathToBarTarget);
+
+        final Map<QName, LeafRefContext> referencedByChilds = leafRefContext.getReferencedByChilds();
+        assertEquals(2, referencedByChilds.size());
+
+        final LeafRefContext rootCtx = referencedByChilds.get(baz("root"));
+        assertEquals(1, rootCtx.getReferencedByChilds().size());
+        assertTrue(rootCtx.getReferencingChilds().isEmpty());
+        assertFalse(rootCtx.isReferencing());
+        assertFalse(rootCtx.isReferenced());
+
+        final LeafRefContext targetCtx = rootCtx.getReferencedChildByName(baz("target"));
+        assertTrue(targetCtx.getReferencedByChilds().isEmpty());
+        assertTrue(targetCtx.getReferencingChilds().isEmpty());
+        assertTrue(targetCtx.isReferenced());
+        assertFalse(targetCtx.isReferencing());
+
+        final Map<QName, LeafRefContext> allReferencedByLeafRefCtxs = targetCtx.getAllReferencedByLeafRefCtxs();
+        assertEquals(6, allReferencedByLeafRefCtxs.size());
+        assertTrue(myLeafCtx == targetCtx.getReferencedByLeafRefCtxByName(foo("my-leaf")));
+    }
+
+    private void assertLeafRef(final LeafRefContext leafRefToTest, final LeafRefPath expectedLeafRefPath) {
+        assertNotNull(leafRefToTest);
+        assertNotNull(expectedLeafRefPath);
+        assertTrue(leafRefToTest.getReferencedByChilds().isEmpty());
+        assertTrue(leafRefToTest.getReferencingChilds().isEmpty());
+        assertFalse(leafRefToTest.isReferenced());
+        assertTrue(leafRefToTest.isReferencing());
+        assertEquals(expectedLeafRefPath, leafRefToTest.getAbsoluteLeafRefTargetPath());
+    }
+
+    private static QName foo(final String localName) {
+        return QName.create(FOO_NS, REV, localName);
+    }
+
+    private static QName bar(final String localName) {
+        return QName.create(BAR_NS, REV, localName);
+    }
+
+    private static QName baz(final String localName) {
+        return QName.create(BAZ_NS, REV, localName);
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/bug7844/bar.yang b/yang/yang-data-impl/src/test/resources/bug7844/bar.yang
new file mode 100644 (file)
index 0000000..8ac871b
--- /dev/null
@@ -0,0 +1,30 @@
+module bar {
+    namespace bar;
+    prefix bar-mod;
+
+    import baz { prefix baz-imp; revision-date 1970-01-01; }
+
+    typedef bar-leafref {
+        type baz-imp:my-leafref;
+        description "bar-leafref";
+    }
+
+    typedef bar-base-leafref {
+        type leafref {
+            path "/baz-imp:root/baz-imp:target";
+        }
+    }
+
+    leaf my-leafref-in-bar {
+        type bar-base-leafref;
+    }
+
+    leaf my-leafref-in-bar-2 {
+        type bar-base-leafref;
+        description "bar-base-leafref-2";
+    }
+
+    leaf bar-target {
+        type string;
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/bug7844/baz.yang b/yang/yang-data-impl/src/test/resources/bug7844/baz.yang
new file mode 100644 (file)
index 0000000..7b746b6
--- /dev/null
@@ -0,0 +1,17 @@
+module baz {
+    namespace baz;
+    prefix baz-mod;
+
+    typedef my-leafref {
+        type leafref {
+            path "/baz-mod:root/baz-mod:target";
+        }
+        description "baz-leafref";
+    }
+
+    container root {
+        leaf target {
+            type string;
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/bug7844/foo.yang b/yang/yang-data-impl/src/test/resources/bug7844/foo.yang
new file mode 100644 (file)
index 0000000..b7f19b4
--- /dev/null
@@ -0,0 +1,39 @@
+module foo {
+    namespace foo;
+    prefix foo-mod;
+
+    import bar { prefix bar-imp; revision-date 1970-01-01; }
+
+    leaf my-leaf {
+        type foo-leafref;
+    }
+
+    typedef foo-leafref {
+        type bar-imp:bar-leafref;
+        description "foo-leafref";
+    }
+
+    leaf my-leaf-2 {
+        type foo-leafref-2;
+    }
+
+    typedef foo-leafref-2 {
+        type bar-imp:bar-base-leafref;
+        description "foo-leaf-ref-2";
+    }
+
+    leaf bar-base-leafref {
+        type bar-imp:bar-base-leafref;
+    }
+
+    leaf bar-base-leafref-2 {
+        type bar-imp:bar-base-leafref;
+        description "bar-base-leafref-2";
+    }
+
+    leaf direct-leafref {
+        type leafref {
+            path "/bar-imp:bar-target";
+        }
+    }
+}