Bug 4656 - Yang parser does not determine configuration true or false properly 93/30193/7
authorPeter Kajsa <pkajsa@cisco.com>
Wed, 25 Nov 2015 12:20:31 +0000 (13:20 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 1 Dec 2015 15:17:35 +0000 (15:17 +0000)
Yang parser does not determine configuration true or false properly,
especially for ChoiceCaseNode.

Change-Id: I86ce4831865f76f0808d554c917094416d4b6338
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/Retest_ConfigStatementValidationTest.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java
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/reactor/RootStatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AbstractEffectiveSimpleDataNodeContainer.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/CaseEffectiveStatementImpl.java

index 9089c509408dc1b1bb1349ec1724ab8cd74705a4..6bb03a55fa39cb0e604d8ac642032dba55c02f3f 100644 (file)
@@ -12,6 +12,7 @@ import static org.junit.Assert.assertNotNull;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -144,7 +145,7 @@ public class Retest_ConfigStatementValidationTest {
 
         final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
         modificationTree.write(ii, case2Cont);
-
+        modificationTree.ready();
         inMemoryDataTree.validate(modificationTree);
         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
         inMemoryDataTree.commit(prepare);
index a762d7fc39dce6bc662d2337cf728509dab7de4f..78d1ef44207c6fa0deff013487e1261fe8f001ab 100644 (file)
@@ -52,6 +52,8 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
      */
     @Nonnull Optional<SchemaPath> getSchemaPath();
 
+    boolean isConfiguration();
+
     @Nonnull
     <K, V, KT extends K, N extends IdentifierNamespace<K, V>> V getFromNamespace(
             Class<N> type, KT key) throws NamespaceNotAvailableException;
index 434ae4065abfb78ffc1a31195c0c011c6e1857af..3e830d80c71c2f409bfa19ef090becef6211ee95 100644 (file)
@@ -81,6 +81,23 @@ public final class StmtContextUtils {
         return null;
     }
 
+    @SuppressWarnings("unchecked")
+    public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstEffectiveSubstatement(
+            final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+        for (StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
+            if (producesDeclared(subStmtContext,declaredType)) {
+                return (StmtContext<AT, ?, ?>) subStmtContext;
+            }
+        }
+        return null;
+    }
+
+    public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstSubstatement(
+            final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+        StmtContext<AT, ?, ?> declaredSubstatement = findFirstDeclaredSubstatement(stmtContext, declaredType);
+        return declaredSubstatement != null ? declaredSubstatement : findFirstEffectiveSubstatement(stmtContext, declaredType);
+    }
+
     @SafeVarargs
     public static StmtContext<?, ?, ?> findFirstDeclaredSubstatement(final StmtContext<?, ?, ?> stmtContext,
             int startIndex, final Class<? extends DeclaredStatement<?>>... types) {
index ee47e07753c6cec5a57478536346caacf8b5acc9..8fe42e1323eb596b78c978736cf876f8c8e6cb9c 100644 (file)
@@ -167,4 +167,9 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
     public boolean isRootContext() {
         return true;
     }
+
+    @Override
+    public boolean isConfiguration() {
+        return true;
+    }
 }
index 4b1773c6a33e97a9611131d3807cf070489d007c..24cb033571b9192bdcf28b1b1e47f017c24d7e6f 100644 (file)
@@ -18,10 +18,12 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace;
@@ -227,4 +229,38 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     public boolean isRootContext() {
         return false;
     }
+
+    @Override
+    public boolean isConfiguration() {
+        StmtContext<Boolean, ?, ?> configStatement = StmtContextUtils
+                .findFirstSubstatement(this, ConfigStatement.class);
+
+        /*
+         * If "config" statement is not specified, the default is the same as
+         * the parent schema node's "config" value.
+         */
+        if (configStatement == null) {
+            return parent.isConfiguration();
+        }
+
+        /*
+         * If a parent node has "config" set to "true", the node underneath it can
+         * have "config" set to "true" or "false".
+         */
+        if (parent.isConfiguration()) {
+            return configStatement.getStatementArgument();
+        }
+
+        /*
+         * If a parent node has "config" set to "false", no node underneath it
+         * can have "config" set to "true", therefore only "false" is permitted.
+         */
+        if (!configStatement.getStatementArgument()) {
+            return false;
+        }
+
+        throw new InferenceException(
+                "Parent node has config statement set to false, therefore no node underneath it can have config set to true",
+                getStatementSourceReference());
+    }
 }
index 835b7f08a8713addb88822ed3b43610a144567bf..43ff80b259c433b65e1dcab74ef14a56e46814ce 100644 (file)
@@ -46,9 +46,7 @@ abstract class AbstractEffectiveSimpleDataNodeContainer<D extends DeclaredStatem
 
         this.path = ctx.getSchemaPath().get();
         this.constraints = EffectiveConstraintDefinitionImpl.forParent(this);
-
-        ConfigEffectiveStatementImpl configStmt = firstEffective(ConfigEffectiveStatementImpl.class);
-        this.configuration = (configStmt == null) ? true : configStmt.argument();
+        this.configuration = ctx.isConfiguration();
 
         // initSubstatementCollectionsAndFields
 
index 57769587c56ab972be64886f539d6fa7a63a0b6a..36d2a13726de043aa2227c3f8bdbcdfa4f9c49b3 100644 (file)
@@ -32,11 +32,6 @@ public final class CaseEffectiveStatementImpl extends AbstractEffectiveSimpleDat
         return Optional.fromNullable(original);
     }
 
-    @Override
-    public boolean isConfiguration() {
-        return false;
-    }
-
     @Override
     public int hashCode() {
         final int prime = 31;