From: Igor Foltin Date: Wed, 14 Dec 2016 11:24:03 +0000 (+0100) Subject: Bug 6871: [YANG 1.1] Allow "must" in "input", "output" and "notification" statements X-Git-Tag: release/carbon~206 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=65454a8ce9e2a63fa138c4f46e9207cabe199a8b;p=yangtools.git Bug 6871: [YANG 1.1] Allow "must" in "input", "output" and "notification" statements Starting with YANG 1.1 (RFC7950), "must" statements can be defined in "input", "output" and "notification" statements. Yang statement parser can now parse models containing such statements. Change-Id: I6b81dd3447bfc50f5a21b79fbdaacfb6e2bf9689 Signed-off-by: Igor Foltin --- diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/InputStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/InputStatementImpl.java index 63fb8eba85..4bf181e748 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/InputStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/InputStatementImpl.java @@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement; import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement; import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement; @@ -102,4 +103,10 @@ public class InputStatementImpl extends AbstractDeclaredStatement public Collection getDataDefinitions() { return allDeclared(DataDefinitionStatement.class); } + + @Nonnull + @Override + public Collection getMusts() { + return allDeclared(MustStatement.class); + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/NotificationStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/NotificationStatementImpl.java index 792961d4e8..a67bfaa783 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/NotificationStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/NotificationStatementImpl.java @@ -16,6 +16,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement; import org.opendaylight.yangtools.yang.model.api.stmt.NotificationStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement; import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement; @@ -119,6 +120,12 @@ public class NotificationStatementImpl extends AbstractDeclaredStatement return allDeclared(DataDefinitionStatement.class); } + @Nonnull + @Override + public Collection getMusts() { + return allDeclared(MustStatement.class); + } + @Nullable @Override public StatusStatement getStatus() { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/OutputStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/OutputStatementImpl.java index 9cf2652be1..a2b1d0446e 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/OutputStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/OutputStatementImpl.java @@ -14,6 +14,7 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement; import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement; import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; @@ -99,5 +100,11 @@ public class OutputStatementImpl extends AbstractDeclaredStatement implem public Collection getDataDefinitions() { return allDeclared(DataDefinitionStatement.class); } + + @Nonnull + @Override + public Collection getMusts() { + return allDeclared(MustStatement.class); + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/NotificationEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/NotificationEffectiveStatementImpl.java index a33d19e7d7..c769f6265b 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/NotificationEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/NotificationEffectiveStatementImpl.java @@ -18,6 +18,7 @@ import java.util.Set; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; @@ -29,6 +30,7 @@ public class NotificationEffectiveStatementImpl extends AbstractEffectiveDocumentedDataNodeContainer implements NotificationDefinition { private final QName qname; private final SchemaPath path; + private final ConstraintDefinition constraints; private final Set augmentations; private final List unknownNodes; @@ -38,6 +40,8 @@ public class NotificationEffectiveStatementImpl extends this.qname = ctx.getStatementArgument(); this.path = ctx.getSchemaPath().get(); + this.constraints = EffectiveConstraintDefinitionImpl.forParent(this); + // initSubstatementCollections Collection> effectiveSubstatements = effectiveSubstatements(); List unknownNodesInit = new LinkedList<>(); @@ -68,6 +72,11 @@ public class NotificationEffectiveStatementImpl extends return path; } + @Override + public ConstraintDefinition getConstraints() { + return constraints; + } + @Override public Set getAvailableAugmentations() { return augmentations; diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/InputStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/InputStatementRfc7950Support.java index 6cf96425ed..675518bb83 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/InputStatementRfc7950Support.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/InputStatementRfc7950Support.java @@ -27,6 +27,7 @@ public final class InputStatementRfc7950Support extends InputStatementImpl.Defin .addAny(YangStmtMapping.LEAF) .addAny(YangStmtMapping.LEAF_LIST) .addAny(YangStmtMapping.LIST) + .addAny(YangStmtMapping.MUST) .addAny(YangStmtMapping.TYPEDEF) .addAny(YangStmtMapping.USES) .build(); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/NotificationStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/NotificationStatementRfc7950Support.java index 5464bf8018..bbb3dbbf89 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/NotificationStatementRfc7950Support.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/NotificationStatementRfc7950Support.java @@ -40,6 +40,7 @@ public final class NotificationStatementRfc7950Support extends NotificationState .addAny(YangStmtMapping.LEAF) .addAny(YangStmtMapping.LEAF_LIST) .addAny(YangStmtMapping.LIST) + .addAny(YangStmtMapping.MUST) .addOptional(YangStmtMapping.REFERENCE) .addOptional(YangStmtMapping.STATUS) .addAny(YangStmtMapping.TYPEDEF) diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/OutputStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/OutputStatementRfc7950Support.java index 92071cb3d8..d0567da0ce 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/OutputStatementRfc7950Support.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/OutputStatementRfc7950Support.java @@ -27,6 +27,7 @@ public final class OutputStatementRfc7950Support extends OutputStatementImpl.Def .addAny(YangStmtMapping.LEAF) .addAny(YangStmtMapping.LEAF_LIST) .addAny(YangStmtMapping.LIST) + .addAny(YangStmtMapping.MUST) .addAny(YangStmtMapping.TYPEDEF) .addAny(YangStmtMapping.USES) .build(); diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java new file mode 100644 index 0000000000..21e2e7f9eb --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java @@ -0,0 +1,82 @@ +/* + * 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.parser.stmt.rfc7950; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.FileNotFoundException; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.Date; +import java.util.Set; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.MustDefinition; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.stmt.StmtTestUtils; + +public class Bug6871Test { + + @Test + public void testValidYang11Model() throws ReactorException, FileNotFoundException, URISyntaxException, + ParseException { + final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6871/foo.yang"); + assertNotNull(schemaContext); + + final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2016-12-14"); + + final Module foo = schemaContext.findModuleByName("foo", revision); + assertNotNull(foo); + + final Set notifications = foo.getNotifications(); + assertEquals(1, notifications.size()); + final NotificationDefinition myNotification = notifications.iterator().next(); + Set mustConstraints = myNotification.getConstraints().getMustConstraints(); + assertEquals(2, mustConstraints.size()); + + final Set rpcs = foo.getRpcs(); + assertEquals(1, rpcs.size()); + final RpcDefinition myRpc = rpcs.iterator().next(); + + final ContainerSchemaNode input = myRpc.getInput(); + assertNotNull(input); + mustConstraints = input.getConstraints().getMustConstraints(); + assertEquals(2, mustConstraints.size()); + + final ContainerSchemaNode output = myRpc.getOutput(); + assertNotNull(output); + mustConstraints = output.getConstraints().getMustConstraints(); + assertEquals(2, mustConstraints.size()); + } + + @Test + public void testInvalidYang10Model() throws FileNotFoundException, URISyntaxException { + assertException("/rfc7950/bug6871/foo10.yang", "MUST is not valid for NOTIFICATION"); + assertException("/rfc7950/bug6871/bar10.yang", "MUST is not valid for INPUT"); + assertException("/rfc7950/bug6871/baz10.yang", "MUST is not valid for OUTPUT"); + } + + private static void assertException(final String sourcePath, final String exceptionMessage) + throws FileNotFoundException, URISyntaxException { + try { + StmtTestUtils.parseYangSource(sourcePath); + fail("Test should fail due to invalid Yang 1.0"); + } catch (final ReactorException ex) { + assertTrue(ex.getCause().getMessage().startsWith(exceptionMessage)); + } + } +} diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang new file mode 100644 index 0000000000..a1ab5af423 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang @@ -0,0 +1,14 @@ +module bar10 { + namespace bar10-namespace; + prefix bar10-prefix; + yang-version 1; + + revision 2016-12-14; + + rpc my-rpc { + input { + must "bar = foo"; + must "c != d"; + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang new file mode 100644 index 0000000000..25e1640ac9 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang @@ -0,0 +1,14 @@ +module baz10 { + namespace baz10-namespace; + prefix baz10-prefix; + yang-version 1; + + revision 2016-12-14; + + rpc my-rpc { + output { + must "baz != bar"; + must "x = y"; + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang new file mode 100644 index 0000000000..fd48d5f637 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang @@ -0,0 +1,24 @@ +module foo { + namespace foo-namespace; + prefix foo-prefix; + yang-version 1.1; + + revision 2016-12-14; + + notification my-notification { + must "foo != bar"; + must "a = b"; + } + + rpc my-rpc { + input { + must "bar = foo"; + must "c != d"; + } + + output { + must "baz != bar"; + must "x = y"; + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang new file mode 100644 index 0000000000..cfbd276ddc --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang @@ -0,0 +1,12 @@ +module foo10 { + namespace foo10-namespace; + prefix foo10-prefix; + yang-version 1; + + revision 2016-12-14; + + notification my-notification { + must "foo != bar"; + must "a = b"; + } +} \ No newline at end of file