Bug 5059: Do not fail when 'refine' targets an extension. 20/33720/2
authorPeter Kajsa <pkajsa@cisco.com>
Tue, 26 Jan 2016 14:13:23 +0000 (15:13 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 30 Jan 2016 03:26:15 +0000 (03:26 +0000)
Yang parser does not fail when 'refine' targets an extension, but
the parser logs a warning and the refine statement is ignored.

Change-Id: I9a4ad46ac254c36b64b44903162361c1e14f4e71
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
(cherry picked from commit d20d90de04fa676f96d117d827fe284370fdc3d9)

yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang [new file with mode: 0644]

index 77b285f16a9a3137dd17a1ac8b6fb3acee136515..05b7f67c333ceab95ede69325755457f7db658c5 100644 (file)
@@ -83,17 +83,37 @@ public final class StmtContextUtils {
     }
 
     @SuppressWarnings("unchecked")
-    public static <AT,DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllDeclaredSubstatement(
+    public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllDeclaredSubstatements(
             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
         ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
-            if (producesDeclared(subStmtContext,declaredType)) {
+            if (producesDeclared(subStmtContext, declaredType)) {
                 listBuilder.add((StmtContext<AT, DT, ?>) subStmtContext);
             }
         }
         return listBuilder.build();
     }
 
+    @SuppressWarnings("unchecked")
+    public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllEffectiveSubstatements(
+            final StmtContext<?, ?, ?> stmtContext, final Class<DT> type) {
+        ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+        for (StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
+            if (producesDeclared(subStmtContext, type)) {
+                listBuilder.add((StmtContext<AT, DT, ?>) subStmtContext);
+            }
+        }
+        return listBuilder.build();
+    }
+
+    public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllSubstatements(
+            final StmtContext<?, ?, ?> stmtContext, final Class<DT> type) {
+        ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+        listBuilder.addAll(findAllDeclaredSubstatements(stmtContext, type));
+        listBuilder.addAll(findAllEffectiveSubstatements(stmtContext, type));
+        return listBuilder.build();
+    }
+
     @SuppressWarnings("unchecked")
     public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstEffectiveSubstatement(
             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
index 7f92ae4a7414928805b306c23105ccbfb396b443..8106aa6350fd0d086d7d6ddaa2df73502e89e7b3 100644 (file)
@@ -28,9 +28,13 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class GroupingUtils {
 
+    private static final Logger LOG = LoggerFactory.getLogger(GroupingUtils.class);
+
     private GroupingUtils() {
         throw new UnsupportedOperationException();
     }
@@ -159,6 +163,13 @@ public final class GroupingUtils {
         StatementContextBase<?, ?, ?> refineTargetNodeCtx = Utils.findNode(usesParentCtx, refineTargetNodeIdentifier);
         Preconditions.checkArgument(refineTargetNodeCtx != null, "Refine target node %s not found. At %s",
                 refineTargetNodeIdentifier, refineCtx.getStatementSourceReference());
+        if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) {
+            LOG.warn("Refine node '{}' in uses '{}' has target node unknown statement '{}'. Refine has been skipped. At line: {}",
+                    refineCtx.getStatementArgument(), refineCtx.getParentContext().getStatementArgument(), refineTargetNodeCtx.getStatementArgument(),
+                    refineCtx.getStatementSourceReference());
+            refineCtx.addAsEffectOfStatement(refineTargetNodeCtx);
+            return;
+        }
 
         addOrReplaceNodes(refineCtx, refineTargetNodeCtx);
         refineCtx.addAsEffectOfStatement(refineTargetNodeCtx);
@@ -177,7 +188,6 @@ public final class GroupingUtils {
             final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
 
         StatementDefinition refineSubstatementDef = refineSubstatementCtx.getPublicDefinition();
-        StatementDefinition refineTargetNodeDef = refineTargetNodeCtx.getPublicDefinition();
 
         SourceException.throwIf(!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx),
             refineSubstatementCtx.getStatementSourceReference(),
index 93069256e59bc049c71c3cbf1b1cfd0faab5e6e7..5fdf765ab1d7677d1aa4e8ef9a2f177cd3809d33 100644 (file)
@@ -8,14 +8,18 @@
 
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
+import java.util.Collection;
 import java.util.Iterator;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
 
 class SchemaNodeIdentifierBuildNamespace extends
         DerivedNamespaceBehaviour<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes<?, ?>>
@@ -32,6 +36,7 @@ class SchemaNodeIdentifierBuildNamespace extends
         throw new UnsupportedOperationException("Direct access to namespace is not supported");
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> getFrom(NamespaceStorageNode storage, SchemaNodeIdentifier key) {
 
@@ -49,13 +54,38 @@ class SchemaNodeIdentifierBuildNamespace extends
                 return null;
             }
         }
-        StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage.getFromLocalStorage(ChildSchemaNodes.class, iterator.next());
-        while(current != null && iterator.hasNext()) {
-            current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current.getFromNamespace(ChildSchemaNodes.class, iterator.next());
+        QName nextPath = iterator.next();
+        StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage
+                .getFromLocalStorage(ChildSchemaNodes.class, nextPath);
+        if(current == null && lookupStartStorage instanceof StmtContext<?, ?, ?>) {
+            return tryToFindUnknownStatement(nextPath.getLocalName(), (Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage);
+        }
+        while (current != null && iterator.hasNext()) {
+            nextPath = iterator.next();
+            StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> nextNodeCtx = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current
+                    .getFromNamespace(ChildSchemaNodes.class, nextPath);
+            if (nextNodeCtx == null) {
+                return tryToFindUnknownStatement(nextPath.getLocalName(), current);
+            } else {
+                current = nextNodeCtx;
+            }
         }
         return current;
     }
 
+    @SuppressWarnings("unchecked")
+    private Mutable<?, ?, EffectiveStatement<?, ?>> tryToFindUnknownStatement(final String localName,
+            final Mutable<?, ?, EffectiveStatement<?, ?>> current) {
+        Collection<StmtContext<?, ?, ?>> unknownSubstatements = StmtContextUtils.findAllSubstatements(current,
+                UnknownStatement.class);
+        for (StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
+            if(unknownSubstatement.rawStatementArgument().equals(localName)) {
+                return (Mutable<?, ?, EffectiveStatement<?, ?>>) unknownSubstatement;
+            }
+        }
+        return null;
+    }
+
     @Override
     public QName getSignificantKey(SchemaNodeIdentifier key) {
         return key.getLastComponent();
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java
new file mode 100644 (file)
index 0000000..35f2437
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 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.stmt.test;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+public class Bug5059 {
+    @Test
+    public void test() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException {
+        SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug5059");
+        assertNotNull(context);
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang
new file mode 100644 (file)
index 0000000..3a35eec
--- /dev/null
@@ -0,0 +1,33 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+
+    revision 2016-01-25 {
+        description "test";
+    }
+
+    grouping my-grouping {
+        container my-container {
+            foo:e2 "e2";
+        }
+        foo:e1 "e1";
+    }
+
+    container root {
+        uses my-grouping {
+            refine e1 {
+                description "new description for e1";
+            }
+            refine my-container/e2 {
+                description "new description for e2";
+            }
+        }
+    }
+
+    extension e1 {
+        argument name;
+    }
+    extension e2 {
+        argument name;
+    }
+}