YANGTOOLS-841: Fix SchemaContextUtil.findNodeInSchemaContext() 29/66829/3
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 2 Jan 2018 10:23:44 +0000 (11:23 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 2 Jan 2018 11:48:36 +0000 (12:48 +0100)
When performing recursive node lookup, consider
{Action,Notification}NodeContainers, so that we correctly resolved
nested actions and notifications -- which are new elements in RFC7950
metamodel.

Also generalized RPC input/output lookup to work on actions, too.

Change-Id: I877061c7f0370caf1ed04eb9420a43af3b2d3915
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YT841Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/YT841/foo.yang [new file with mode: 0644]

index 8e390ba7bee45fbbe26bf9fa0b2f18c02884fb5c..478629ef5447522742bccc867fddd22a70229cbe 100644 (file)
@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -34,6 +35,8 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -365,8 +368,24 @@ public final class SchemaContextUtil {
             }
         }
 
-        if (foundNode == null && parent instanceof RpcDefinition) {
-            final RpcDefinition parentRpcDefinition = (RpcDefinition) parent;
+        if (foundNode == null && parent instanceof ActionNodeContainer) {
+            foundNode = ((ActionNodeContainer) parent).getActions().stream()
+                    .filter(act -> current.equals(act.getQName())).findFirst().orElse(null);
+            if (foundNode != null && nextPath.iterator().hasNext()) {
+                foundNode = findNodeIn(foundNode, nextPath);
+            }
+        }
+
+        if (foundNode == null && parent instanceof NotificationNodeContainer) {
+            foundNode = ((NotificationNodeContainer) parent).getNotifications().stream()
+                    .filter(notif -> current.equals(notif.getQName())).findFirst().orElse(null);
+            if (foundNode != null && nextPath.iterator().hasNext()) {
+                foundNode = findNodeIn(foundNode, nextPath);
+            }
+        }
+
+        if (foundNode == null && parent instanceof OperationDefinition) {
+            final OperationDefinition parentRpcDefinition = (OperationDefinition) parent;
 
             if (current.getLocalName().equals("input")) {
                 foundNode = parentRpcDefinition.getInput();
@@ -448,7 +467,7 @@ public final class SchemaContextUtil {
         return null;
     }
 
-    private static GroupingDefinition getGroupingByName(final RpcDefinition rpc, final QName name) {
+    private static GroupingDefinition getGroupingByName(final OperationDefinition rpc, final QName name) {
         for (final GroupingDefinition grouping : rpc.getGroupings()) {
             if (grouping.getQName().equals(name)) {
                 return grouping;
@@ -674,7 +693,7 @@ public final class SchemaContextUtil {
         final TypeDefinition<?> targetTypeDefinition = typeDefinition(dataSchemaNode);
 
         if (targetTypeDefinition instanceof LeafrefTypeDefinition) {
-            return getBaseTypeForLeafRef(((LeafrefTypeDefinition) targetTypeDefinition), schemaContext, dataSchemaNode);
+            return getBaseTypeForLeafRef((LeafrefTypeDefinition) targetTypeDefinition, schemaContext, dataSchemaNode);
         }
 
         return targetTypeDefinition;
@@ -703,7 +722,7 @@ public final class SchemaContextUtil {
             parentModule, strippedPathStatement);
         final TypeDefinition<?> targetTypeDefinition = typeDefinition(dataSchemaNode);
         if (targetTypeDefinition instanceof LeafrefTypeDefinition) {
-            return getBaseTypeForLeafRef(((LeafrefTypeDefinition) targetTypeDefinition), schemaContext, dataSchemaNode);
+            return getBaseTypeForLeafRef((LeafrefTypeDefinition) targetTypeDefinition, schemaContext, dataSchemaNode);
         }
 
         return targetTypeDefinition;
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YT841Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YT841Test.java
new file mode 100644 (file)
index 0000000..0145bad
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies, s.r.o. 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.stmt;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+
+public class YT841Test {
+    private static final QNameModule FOO = QNameModule.create(URI.create("foo"), QName.parseRevision("2018-01-02"));
+
+    @Test
+    public void testFindDataSchemaNode() throws Exception {
+        final SchemaContext context = StmtTestUtils.parseYangSources("/bugs/YT841/");
+        final Module foo = context.findModuleByNamespace(URI.create("foo")).iterator().next();
+        assertNotNull(foo);
+
+        final SchemaNode target = SchemaContextUtil.findDataSchemaNode(context, SchemaPath.create(true,
+            QName.create(FOO, "foo"),
+            QName.create(FOO, "foo"),
+            QName.create(FOO, "foo"),
+            QName.create(FOO, "input")));
+        assertNotNull(target);
+
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/YT841/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/YT841/foo.yang
new file mode 100644 (file)
index 0000000..966f430
--- /dev/null
@@ -0,0 +1,19 @@
+module foo {
+    yang-version 1.1;
+    namespace foo;
+    prefix foo;
+
+    revision "2018-01-02";
+
+    container foo {
+        list foo {
+            leaf bar {
+                type string;
+            }
+            key bar;
+
+            action foo {
+            }
+        }
+    }
+}