From b5799487138d59c2720cbb519af82e567d7b07c6 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Thu, 2 Jun 2016 16:31:06 +0200 Subject: [PATCH] Bug 5942: When condition of uses node is not exposed by the YANG parser 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 Signed-off-by: Robert Varga --- .../yang/model/api/DocumentedNode.java | 3 + .../yangtools/yang/model/api/UsesNode.java | 30 +++++++++- .../effective/UsesEffectiveStatementImpl.java | 36 ++++++++---- .../yangtools/yang/stmt/Bug5942Test.java | 55 +++++++++++++++++++ .../src/test/resources/bugs/bug5942/foo.yang | 25 +++++++++ 5 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5942Test.java create mode 100644 yang/yang-parser-impl/src/test/resources/bugs/bug5942/foo.yang diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DocumentedNode.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DocumentedNode.java index 36acbe9b51..f430925584 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DocumentedNode.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DocumentedNode.java @@ -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 * status substatement */ + @Nullable Status getStatus(); } diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/UsesNode.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/UsesNode.java index 113767487c..f825718139 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/UsesNode.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/UsesNode.java @@ -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; * uses 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 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 getWhenCondition() { + return Optional.absent(); + } + + /** + * + * Returns unknown schema nodes which belongs to this instance of the type + * UsesNode. + * + * @return list of unknown schema nodes defined under this uses node. + */ + default List getUnknownSchemaNodes() { + return ImmutableList.of(); + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UsesEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UsesEffectiveStatementImpl.java index aec4f83b7b..b212011a5e 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UsesEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UsesEffectiveStatementImpl.java @@ -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 implements UsesNode { +public final class UsesEffectiveStatementImpl extends AbstractEffectiveDocumentedNode implements UsesNode { private final SchemaPath groupingPath; private final boolean addedByUses; private final Map refines; private final Set augmentations; private final List unknownNodes; + private final RevisionAwareXPath whenCondition; public UsesEffectiveStatementImpl( final StmtContext> ctx) { super(ctx); // initGroupingPath - StmtContext> grpCtx = ctx.getFromNamespace( + final StmtContext> grpCtx = ctx.getFromNamespace( GroupingNamespace.class, ctx.getStatementArgument()); this.groupingPath = grpCtx.getSchemaPath().get(); // initCopyType - List copyTypesFromOriginal = ctx.getCopyHistory(); + final List 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> effectiveSubstatements = effectiveSubstatements(); - List unknownNodesInit = new LinkedList<>(); - Set augmentationsInit = new HashSet<>(); - Map refinesInit = new HashMap<>(); - for (EffectiveStatement effectiveStatement : effectiveSubstatements) { + final Collection> effectiveSubstatements = effectiveSubstatements(); + final List unknownNodesInit = new LinkedList<>(); + final Set augmentationsInit = new HashSet<>(); + final Map 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 getUnknownSchemaNodes() { return unknownNodes; } + @Override + public Optional 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 index 0000000000..fe30d5a15c --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5942Test.java @@ -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 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 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 index 0000000000..006277d304 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/bugs/bug5942/foo.yang @@ -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; + } +} -- 2.36.6