Bug 5942: When condition of uses node is not exposed by the YANG parser 75/39775/6
authorPeter Kajsa <pkajsa@cisco.com>
Thu, 2 Jun 2016 14:31:06 +0000 (16:31 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 7 Jul 2016 08:24:32 +0000 (08:24 +0000)
Interface UsesNode does not provide any method to obtain When condition,
Description, Status, Reference and UnknownNodes defined in yang source.
This patch provides API definition and its implementation necessary to get
these substatements of UsesNode.

Change-Id: I51e182de247a9375e4e28d76d7fecb421721cfc4
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DocumentedNode.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/UsesNode.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UsesEffectiveStatementImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5942Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug5942/foo.yang [new file with mode: 0644]

index 36acbe9b5168c770bbff5558bf1d736b065bafea..f4309255843a28678efa7a00db164208b0c77733 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.model.api;
 
+import javax.annotation.Nullable;
+
 /**
  *
  * Node which can have documentation assigned.
@@ -40,5 +42,6 @@ public interface DocumentedNode {
      * @return status of this node which represents the argument of the YANG
      *         <code>status</code> substatement
      */
+    @Nullable
     Status getStatus();
 }
index 113767487c8fd2d53a2d4e3e28d3460e57e9da84..f825718139222ca373939820bcb77e306eaab114 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.model.api;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -15,7 +18,7 @@ import java.util.Set;
  * <code>uses</code> substatement.
  *
  */
-public interface UsesNode {
+public interface UsesNode extends DocumentedNode {
 
     /**
      * Returns the schema path to used grouping.
@@ -58,4 +61,29 @@ public interface UsesNode {
      *         refined node
      */
     Map<SchemaPath, SchemaNode> getRefines();
+
+    /**
+     * Returns when statement
+     *
+     * If when condition is present node defined by the parent data definition
+     * statement is only valid when the returned XPath expression conceptually
+     * evaluates to "true" for a particular instance, then the node defined by
+     * the parent data definition statement is valid; otherwise, it is not.
+     *
+     * @return Optional of XPath condition
+     */
+    default Optional<RevisionAwareXPath> getWhenCondition() {
+        return Optional.absent();
+    }
+
+    /**
+     *
+     * Returns unknown schema nodes which belongs to this instance of the type
+     * <code>UsesNode</code>.
+     *
+     * @return list of unknown schema nodes defined under this uses node.
+     */
+    default List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return ImmutableList.of();
+    }
 }
index aec4f83b7b56836cd6d9925dc7a96fb5d30b9885..b212011a5e5b00ad6732520790cd3562ec0ddc67 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -20,6 +21,7 @@ import java.util.Objects;
 import java.util.Set;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
@@ -32,24 +34,25 @@ import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
 
-public final class UsesEffectiveStatementImpl extends DeclaredEffectiveStatementBase<QName, UsesStatement> implements UsesNode {
+public final class UsesEffectiveStatementImpl extends AbstractEffectiveDocumentedNode<QName, UsesStatement> implements UsesNode {
     private final SchemaPath groupingPath;
     private final boolean addedByUses;
     private final Map<SchemaPath, SchemaNode> refines;
     private final Set<AugmentationSchema> augmentations;
     private final List<UnknownSchemaNode> unknownNodes;
+    private final RevisionAwareXPath whenCondition;
 
     public UsesEffectiveStatementImpl(
             final StmtContext<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> ctx) {
         super(ctx);
 
         // initGroupingPath
-        StmtContext<?, GroupingStatement, EffectiveStatement<QName, GroupingStatement>> grpCtx = ctx.getFromNamespace(
+        final StmtContext<?, GroupingStatement, EffectiveStatement<QName, GroupingStatement>> grpCtx = ctx.getFromNamespace(
                 GroupingNamespace.class, ctx.getStatementArgument());
         this.groupingPath = grpCtx.getSchemaPath().get();
 
         // initCopyType
-        List<TypeOfCopy> copyTypesFromOriginal = ctx.getCopyHistory();
+        final List<TypeOfCopy> copyTypesFromOriginal = ctx.getCopyHistory();
         if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES)) {
             addedByUses = true;
         } else {
@@ -57,28 +60,31 @@ public final class UsesEffectiveStatementImpl extends DeclaredEffectiveStatement
         }
 
         // initSubstatementCollections
-        Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements = effectiveSubstatements();
-        List<UnknownSchemaNode> unknownNodesInit = new LinkedList<>();
-        Set<AugmentationSchema> augmentationsInit = new HashSet<>();
-        Map<SchemaPath, SchemaNode> refinesInit = new HashMap<>();
-        for (EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements) {
+        final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements = effectiveSubstatements();
+        final List<UnknownSchemaNode> unknownNodesInit = new LinkedList<>();
+        final Set<AugmentationSchema> augmentationsInit = new HashSet<>();
+        final Map<SchemaPath, SchemaNode> refinesInit = new HashMap<>();
+        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements) {
             if (effectiveStatement instanceof UnknownSchemaNode) {
-                UnknownSchemaNode unknownNode = (UnknownSchemaNode) effectiveStatement;
+                final UnknownSchemaNode unknownNode = (UnknownSchemaNode) effectiveStatement;
                 unknownNodesInit.add(unknownNode);
             }
             if (effectiveStatement instanceof AugmentationSchema) {
-                AugmentationSchema augmentationSchema = (AugmentationSchema) effectiveStatement;
+                final AugmentationSchema augmentationSchema = (AugmentationSchema) effectiveStatement;
                 augmentationsInit.add(augmentationSchema);
             }
             if (effectiveStatement instanceof RefineEffectiveStatementImpl) {
-                RefineEffectiveStatementImpl refineStmt = (RefineEffectiveStatementImpl) effectiveStatement;
-                SchemaNodeIdentifier identifier = refineStmt.argument();
+                final RefineEffectiveStatementImpl refineStmt = (RefineEffectiveStatementImpl) effectiveStatement;
+                final SchemaNodeIdentifier identifier = refineStmt.argument();
                 refinesInit.put(identifier.asSchemaPath(), refineStmt.getRefineTargetNode());
             }
         }
         this.unknownNodes = ImmutableList.copyOf(unknownNodesInit);
         this.augmentations = ImmutableSet.copyOf(augmentationsInit);
         this.refines = ImmutableMap.copyOf(refinesInit);
+
+        final WhenEffectiveStatementImpl whenStmt = firstEffective(WhenEffectiveStatementImpl.class);
+        this.whenCondition = (whenStmt == null) ? null : whenStmt.argument();
     }
 
     @Override
@@ -106,10 +112,16 @@ public final class UsesEffectiveStatementImpl extends DeclaredEffectiveStatement
         return refines;
     }
 
+    @Override
     public List<UnknownSchemaNode> getUnknownSchemaNodes() {
         return unknownNodes;
     }
 
+    @Override
+    public Optional<RevisionAwareXPath> getWhenCondition() {
+        return Optional.fromNullable(whenCondition);
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5942Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5942Test.java
new file mode 100644 (file)
index 0000000..fe30d5a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+public class Bug5942Test {
+    @Test
+    public void test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSources("/bugs/bug5942");
+        assertNotNull(schemaContext);
+
+        final DataSchemaNode root = schemaContext.getDataChildByName(QName.create("foo", "2016-06-02", "root"));
+        assertTrue(root instanceof ContainerSchemaNode);
+
+        final Set<UsesNode> uses = ((ContainerSchemaNode) root).getUses();
+        assertEquals(1, uses.size());
+        final UsesNode usesNode = uses.iterator().next();
+
+        assertEquals("uses description", usesNode.getDescription());
+        assertEquals("uses reference", usesNode.getReference());
+        assertEquals(Status.DEPRECATED, usesNode.getStatus());
+        assertEquals(new RevisionAwareXPathImpl("0!=1", false), usesNode.getWhenCondition().get());
+
+        final List<UnknownSchemaNode> unknownSchemaNodes = usesNode.getUnknownSchemaNodes();
+        assertEquals(1, unknownSchemaNodes.size());
+        final UnknownSchemaNode unknownSchemaNode = unknownSchemaNodes.iterator().next();
+        assertEquals("argument", unknownSchemaNode.getNodeParameter());
+        assertEquals(QName.create("foo", "2016-06-02", "e"), unknownSchemaNode.getExtensionDefinition().getQName());
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug5942/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug5942/foo.yang
new file mode 100644 (file)
index 0000000..006277d
--- /dev/null
@@ -0,0 +1,25 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+    yang-version 1;
+
+    revision "2016-06-02";
+
+    grouping grp {
+        container bar;
+    }
+
+    container root {
+        uses grp {
+            description "uses description";
+            reference "uses reference";
+            status "deprecated";
+            when "0!=1";
+            foo:e "argument";
+        }
+    }
+
+    extension e {
+        argument name;
+    }
+}