From 6d1a7c4cdf2153bd7857e9ef83ccdbe8fde6b994 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Mon, 12 Dec 2016 13:23:45 +0100 Subject: [PATCH] Bug 6869: [Yang 1.1] Allow if-feature in bit, enum, refine & identity Allow "if-feature" in "bit", "enum", "identity" and "refine" statements. Presence of an "if-feature" statement in a "bit" statement does not affect the automatically assigned position. Change-Id: I487620bc08fc4f57c51172821087feaad04db5fe Signed-off-by: Peter Kajsa --- .../parser/stmt/rfc6020/BitStatementImpl.java | 8 ++ .../stmt/rfc6020/EnumStatementImpl.java | 8 ++ .../stmt/rfc6020/IdentityStatementImpl.java | 8 ++ .../stmt/rfc6020/RefineStatementImpl.java | 9 ++ .../stmt/rfc6020/UsesStatementImpl.java | 12 +- .../stmt/rfc6020/YangInferencePipeline.java | 16 ++- .../rfc7950/BitStatementRfc7950Support.java | 33 ++++++ .../rfc7950/EnumStatementRfc7950Support.java | 33 ++++++ .../IdentityStatementRfc7950Support.java | 33 ++++++ .../RefineStatementRfc7950Support.java | 39 +++++++ .../yang/parser/stmt/rfc7950/Bug6869Test.java | 107 ++++++++++++++++++ .../yangtools/yang/stmt/StmtTestUtils.java | 31 +++-- .../test/resources/rfc7950/bug6869/foo.yang | 48 ++++++++ .../resources/rfc7950/bug6869/invalid10.yang | 8 ++ 14 files changed, 377 insertions(+), 16 deletions(-) create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/BitStatementRfc7950Support.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/EnumStatementRfc7950Support.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/IdentityStatementRfc7950Support.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/RefineStatementRfc7950Support.java create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6869Test.java create mode 100644 yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/foo.yang create mode 100644 yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/invalid10.yang diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/BitStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/BitStatementImpl.java index c062ff10b2..7bb4cfe544 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/BitStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/BitStatementImpl.java @@ -7,12 +7,14 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Collection; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; 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.BitStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement; import org.opendaylight.yangtools.yang.model.api.stmt.PositionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement; import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement; @@ -81,6 +83,12 @@ public class BitStatementImpl extends AbstractDeclaredStatement implement return firstDeclared(DescriptionStatement.class); } + @Nonnull + @Override + public Collection getIfFeatures() { + return allDeclared(IfFeatureStatement.class); + } + @Override public ReferenceStatement getReference() { return firstDeclared(ReferenceStatement.class); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/EnumStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/EnumStatementImpl.java index afa17be9b1..74b0ee896d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/EnumStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/EnumStatementImpl.java @@ -7,11 +7,13 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Collection; import javax.annotation.Nonnull; 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.DescriptionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.EnumStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement; import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ValueStatement; @@ -81,6 +83,12 @@ public class EnumStatementImpl extends AbstractDeclaredStatement impleme return firstDeclared(DescriptionStatement.class); } + @Nonnull + @Override + public Collection getIfFeatures() { + return allDeclared(IfFeatureStatement.class); + } + @Override public ReferenceStatement getReference() { return firstDeclared(ReferenceStatement.class); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/IdentityStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/IdentityStatementImpl.java index a4fa2a9e5a..32373d8ee5 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/IdentityStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/IdentityStatementImpl.java @@ -7,6 +7,7 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Collection; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; @@ -14,6 +15,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.BaseStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.IdentityStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement; import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement; import org.opendaylight.yangtools.yang.parser.spi.IdentityNamespace; @@ -89,6 +91,12 @@ public class IdentityStatementImpl extends AbstractDeclaredStatement return firstDeclared(DescriptionStatement.class); } + @Nonnull + @Override + public Collection getIfFeatures() { + return allDeclared(IfFeatureStatement.class); + } + @Override public ReferenceStatement getReference() { return firstDeclared(ReferenceStatement.class); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/RefineStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/RefineStatementImpl.java index 5da200a7e5..3bd6ada915 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/RefineStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/RefineStatementImpl.java @@ -8,10 +8,13 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Collection; +import javax.annotation.Nonnull; import javax.annotation.Nullable; 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.DescriptionStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement; import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; @@ -86,6 +89,12 @@ public class RefineStatementImpl extends AbstractDeclaredStatement getIfFeatures() { + return allDeclared(IfFeatureStatement.class); + } + @Nullable @Override public ReferenceStatement getReference() { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java index 61860be3d3..e97a9771be 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java @@ -15,6 +15,7 @@ import java.util.Set; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.YangVersion; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; @@ -267,12 +268,21 @@ public class UsesStatementImpl extends AbstractDeclaredStatement implemen final Mutable> usesNode, final StatementContextBase targetNodeStmtCtx) { for (final StatementContextBase subStmtCtx : usesNode.declaredSubstatements()) { - if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)) { + if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class) + && areFeaturesSupported(subStmtCtx)) { performRefine(subStmtCtx, targetNodeStmtCtx); } } } + private static boolean areFeaturesSupported(final StatementContextBase subStmtCtx) { + /* + * In case of Yang 1.1, checks whether features are supported. + */ + return !YangVersion.VERSION_1_1.equals(subStmtCtx.getRootVersion()) || StmtContextUtils + .areFeaturesSupported(subStmtCtx); + } + private static void performRefine(final StatementContextBase refineCtx, final StatementContextBase usesParentCtx) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java index cf844977fa..4b746b2376 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java @@ -63,10 +63,13 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ActionStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.AnydataStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.AugmentStatementRfc7950Support; +import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.BitStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.CaseStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ChoiceStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ContainerStatementRfc7950Support; +import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.EnumStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.GroupingStatementRfc7950Support; +import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.IdentityStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ImportStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.IncludeStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.InputStatementRfc7950Support; @@ -74,6 +77,7 @@ import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ListStatementRfc7950S import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ModuleStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.NotificationStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.OutputStatementRfc7950Support; +import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.RefineStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.SubmoduleStatementRfc7950Support; public final class YangInferencePipeline { @@ -147,16 +151,19 @@ public final class YangInferencePipeline { .addSupport(global(ExtensionNamespace.class)) .addSupport(new TypedefStatementImpl.Definition()) .addSupport(treeScoped(TypeNamespace.class)) - .addSupport(new IdentityStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1, new IdentityStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1_1, new IdentityStatementRfc7950Support()) .addSupport(global(IdentityNamespace.class)) .addSupport(new DefaultStatementImpl.Definition()) .addSupport(new StatusStatementImpl.Definition()) .addSupport(new TypeStatementImpl.Definition()) .addSupport(new UnitsStatementImpl.Definition()) .addSupport(new RequireInstanceStatementImpl.Definition()) - .addSupport(new BitStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1, new BitStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1_1, new BitStatementRfc7950Support()) .addSupport(new PathStatementImpl.Definition()) - .addSupport(new EnumStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1, new EnumStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1_1, new EnumStatementRfc7950Support()) .addSupport(new LengthStatementImpl.Definition()) .addSupport(new PatternStatementImpl.Definition()) .addSupport(new RangeStatementImpl.Definition()) @@ -210,7 +217,8 @@ public final class YangInferencePipeline { .addVersionSpecificSupport(VERSION_1, new AugmentStatementImpl.Definition()) .addVersionSpecificSupport(VERSION_1_1, new AugmentStatementRfc7950Support()) .addSupport(treeScoped(AugmentToChoiceNamespace.class)) - .addSupport(new RefineStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1, new RefineStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1_1, new RefineStatementRfc7950Support()) .addSupport(new FeatureStatementImpl.Definition()) .addSupport(new PositionStatementImpl.Definition()) .addSupport(new ValueStatementImpl.Definition()) diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/BitStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/BitStatementRfc7950Support.java new file mode 100644 index 0000000000..2ec80d0798 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/BitStatementRfc7950Support.java @@ -0,0 +1,33 @@ +/* + * 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 com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; +import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.BitStatementImpl; + +/** + * Class providing necessary support for processing YANG 1.1 Bit statement. + */ +@Beta +public final class BitStatementRfc7950Support extends BitStatementImpl.Definition { + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping + .BIT) + .addOptional(YangStmtMapping.DESCRIPTION) + .addAny(YangStmtMapping.IF_FEATURE) + .addOptional(YangStmtMapping.REFERENCE) + .addOptional(YangStmtMapping.STATUS) + .addOptional(YangStmtMapping.POSITION) + .build(); + + @Override + protected SubstatementValidator getSubstatementValidator() { + return SUBSTATEMENT_VALIDATOR; + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/EnumStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/EnumStatementRfc7950Support.java new file mode 100644 index 0000000000..a3dddbd975 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/EnumStatementRfc7950Support.java @@ -0,0 +1,33 @@ +/* + * 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 com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; +import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.EnumStatementImpl; + +/** + * Class providing necessary support for processing YANG 1.1 Enum statement. + */ +@Beta +public final class EnumStatementRfc7950Support extends EnumStatementImpl.Definition { + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping + .ENUM) + .addOptional(YangStmtMapping.DESCRIPTION) + .addAny(YangStmtMapping.IF_FEATURE) + .addOptional(YangStmtMapping.REFERENCE) + .addOptional(YangStmtMapping.STATUS) + .addOptional(YangStmtMapping.VALUE) + .build(); + + @Override + protected SubstatementValidator getSubstatementValidator() { + return SUBSTATEMENT_VALIDATOR; + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/IdentityStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/IdentityStatementRfc7950Support.java new file mode 100644 index 0000000000..f711464a4c --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/IdentityStatementRfc7950Support.java @@ -0,0 +1,33 @@ +/* + * 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 com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; +import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.IdentityStatementImpl; + +/** + * Class providing necessary support for processing YANG 1.1 Identity statement. + */ +@Beta +public final class IdentityStatementRfc7950Support extends IdentityStatementImpl.Definition { + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping + .IDENTITY) + .addOptional(YangStmtMapping.BASE) + .addOptional(YangStmtMapping.DESCRIPTION) + .addAny(YangStmtMapping.IF_FEATURE) + .addOptional(YangStmtMapping.REFERENCE) + .addOptional(YangStmtMapping.STATUS) + .build(); + + @Override + protected SubstatementValidator getSubstatementValidator() { + return SUBSTATEMENT_VALIDATOR; + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/RefineStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/RefineStatementRfc7950Support.java new file mode 100644 index 0000000000..f242416a16 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/RefineStatementRfc7950Support.java @@ -0,0 +1,39 @@ +/* + * 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 com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; +import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.RefineStatementImpl; + +/** + * Class providing necessary support for processing YANG 1.1 Refine statement. + */ +@Beta +public final class RefineStatementRfc7950Support extends RefineStatementImpl.Definition { + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping + .REFINE) + .addOptional(YangStmtMapping.DEFAULT) + .addOptional(YangStmtMapping.DESCRIPTION) + .addOptional(YangStmtMapping.REFERENCE) + .addOptional(YangStmtMapping.CONFIG) + .addAny(YangStmtMapping.IF_FEATURE) + .addOptional(YangStmtMapping.MANDATORY) + .addOptional(YangStmtMapping.PRESENCE) + .addAny(YangStmtMapping.MUST) + .addOptional(YangStmtMapping.MIN_ELEMENTS) + .addOptional(YangStmtMapping.MAX_ELEMENTS) + .build(); + + @Override + protected SubstatementValidator getSubstatementValidator() { + return SUBSTATEMENT_VALIDATOR; + } +} diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6869Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6869Test.java new file mode 100644 index 0000000000..5228b79914 --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6869Test.java @@ -0,0 +1,107 @@ +/* + * 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.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import java.io.FileNotFoundException; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import org.opendaylight.yangtools.yang.stmt.StmtTestUtils; + +public class Bug6869Test { + private static final String FOO_NS = "foo"; + private static final String FOO_REV = "1970-01-01"; + + @Test + public void identityNoFeaureTest() throws ReactorException, SourceException, FileNotFoundException, + URISyntaxException { + final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6869/foo.yang", + createIfFeaturesPredicate("no-feature")); + assertNotNull(schemaContext); + + final Set identities = getIdentities(schemaContext); + assertEquals(0, identities.size()); + + final SchemaNode findNode = findNode(schemaContext, ImmutableList.of("root", "grp-leaf")); + assertTrue(findNode instanceof LeafSchemaNode); + final LeafSchemaNode grpLeaf = (LeafSchemaNode) findNode; + assertFalse(grpLeaf.getConstraints().isMandatory()); + } + + @Test + public void identityAllFeauresTest() throws ReactorException, SourceException, FileNotFoundException, + URISyntaxException { + final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6869/foo.yang", + createIfFeaturesPredicate("identity-feature", "mandatory-leaf", "tls", "ssh", "two", "three")); + assertNotNull(schemaContext); + + final Set identities = getIdentities(schemaContext); + assertEquals(1, identities.size()); + + final SchemaNode findNode = findNode(schemaContext, ImmutableList.of("root", "grp-leaf")); + assertTrue(findNode instanceof LeafSchemaNode); + final LeafSchemaNode grpLeaf = (LeafSchemaNode) findNode; + assertTrue(grpLeaf.getConstraints().isMandatory()); + } + + private static Set getIdentities(final SchemaContext schemaContext) { + final Set modules = schemaContext.getModules(); + assertEquals(1, modules.size()); + final Module module = modules.iterator().next(); + return module.getIdentities(); + } + + private static Predicate createIfFeaturesPredicate(final String... featureNames) { + final Predicate ifFeaturesPredicate = qName -> { + final Set supportedFeatures = new HashSet<>(); + for (final String featureName : featureNames) { + supportedFeatures.add(QName.create(FOO_NS, FOO_REV, featureName)); + } + return supportedFeatures.contains(qName); + }; + return ifFeaturesPredicate; + } + + private static SchemaNode findNode(final SchemaContext context, final Iterable localNamesPath) { + final Iterable qNames = Iterables.transform(localNamesPath, + localName -> QName.create(FOO_NS, FOO_REV, localName)); + return SchemaContextUtil.findDataSchemaNode(context, SchemaPath.create(qNames, true)); + } + + @Test + public void invalidYang10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException { + try { + StmtTestUtils.parseYangSource("/rfc7950/bug6869/invalid10.yang"); + fail("Test should fail due to invalid Yang 1.0"); + } catch (final SomeModifiersUnresolvedException e) { + assertTrue(e.getCause().getMessage().startsWith("IF_FEATURE is not valid for IDENTITY")); + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/StmtTestUtils.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/StmtTestUtils.java index e6336f273b..a3435cabc5 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/StmtTestUtils.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/StmtTestUtils.java @@ -17,11 +17,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.function.Predicate; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleImport; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.repo.api.IfFeaturePredicates; import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode; import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; @@ -98,13 +101,13 @@ public class StmtTestUtils { public static SchemaContext parseYangSources(final StatementStreamSource... sources) throws SourceException, ReactorException { - return parseYangSources(StatementParserMode.DEFAULT_MODE, sources); + return parseYangSources(StatementParserMode.DEFAULT_MODE, IfFeaturePredicates.ALL_FEATURES, sources); } - public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final StatementStreamSource... sources) + public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final Predicate ifFeaturePredicate, final StatementStreamSource... sources) throws SourceException, ReactorException { - final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode); + final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode, ifFeaturePredicate); reactor.addSources(sources); return reactor.buildEffective(); @@ -112,10 +115,10 @@ public class StmtTestUtils { public static SchemaContext parseYangSources(final File... files) throws SourceException, ReactorException, FileNotFoundException { - return parseYangSources(StatementParserMode.DEFAULT_MODE, files); + return parseYangSources(StatementParserMode.DEFAULT_MODE, IfFeaturePredicates.ALL_FEATURES, files); } - public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final File... files) throws SourceException, + public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final Predicate ifFeaturePredicate, final File... files) throws SourceException, ReactorException, FileNotFoundException { final StatementStreamSource[] sources = new StatementStreamSource[files.length]; @@ -124,7 +127,7 @@ public class StmtTestUtils { sources[i] = new YangStatementSourceImpl(new NamedFileInputStream(files[i], files[i].getPath())); } - return parseYangSources(statementParserMode, sources); + return parseYangSources(statementParserMode, ifFeaturePredicate, sources); } public static SchemaContext parseYangSources(final Collection files) throws SourceException, ReactorException, @@ -134,7 +137,7 @@ public class StmtTestUtils { public static SchemaContext parseYangSources(final Collection files, final StatementParserMode statementParserMode) throws SourceException, ReactorException, FileNotFoundException { - return parseYangSources(statementParserMode, files.toArray(new File[files.size()])); + return parseYangSources(statementParserMode, IfFeaturePredicates.ALL_FEATURES, files.toArray(new File[files.size()])); } public static SchemaContext parseYangSources(final String yangSourcesDirectoryPath) throws SourceException, @@ -144,14 +147,20 @@ public class StmtTestUtils { public static SchemaContext parseYangSource(final String yangSourcePath) throws SourceException, ReactorException, FileNotFoundException, URISyntaxException { - return parseYangSource(yangSourcePath, StatementParserMode.DEFAULT_MODE); + return parseYangSource(yangSourcePath, StatementParserMode.DEFAULT_MODE, IfFeaturePredicates.ALL_FEATURES); + } + + public static SchemaContext parseYangSource(final String yangSourcePath, final Predicate ifFeaturesPredicate) + throws SourceException, FileNotFoundException, ReactorException, URISyntaxException { + return parseYangSource(yangSourcePath, StatementParserMode.DEFAULT_MODE, ifFeaturesPredicate); } - public static SchemaContext parseYangSource(final String yangSourcePath, final StatementParserMode statementParserMode) + public static SchemaContext parseYangSource(final String yangSourcePath, + final StatementParserMode statementParserMode, final Predicate ifFeaturePredicate) throws SourceException, ReactorException, FileNotFoundException, URISyntaxException { final URL source = StmtTestUtils.class.getResource(yangSourcePath); final File sourceFile = new File(source.toURI()); - return parseYangSources(statementParserMode, sourceFile); + return parseYangSources(statementParserMode, ifFeaturePredicate, sourceFile); } public static SchemaContext parseYangSources(final String yangSourcesDirectoryPath, final StatementParserMode statementParserMode) @@ -160,7 +169,7 @@ public class StmtTestUtils { final URL resourceDir = StmtTestUtils.class.getResource(yangSourcesDirectoryPath); final File testSourcesDir = new File(resourceDir.toURI()); - return parseYangSources(statementParserMode, testSourcesDir.listFiles(YANG_FILE_FILTER)); + return parseYangSources(statementParserMode, IfFeaturePredicates.ALL_FEATURES, testSourcesDir.listFiles(YANG_FILE_FILTER)); } public static SchemaContext parseYinSources(final String yinSourcesDirectoryPath, final StatementParserMode statementParserMode) diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/foo.yang new file mode 100644 index 0000000000..b1b4b5b4a9 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/foo.yang @@ -0,0 +1,48 @@ +module foo { + namespace "foo"; + prefix foo; + yang-version 1.1; + + identity my-identity { + if-feature identity-feature; + } + + container root { + uses grp { + refine grp-leaf { + if-feature mandatory-leaf; + mandatory true; + } + } + } + + grouping grp { + leaf grp-leaf { + type empty; + } + } + + typedef my-enum { + type enumeration { + enum tcp; + enum ssh { + if-feature ssh; + } + enum tls { + if-feature tls; + } + } + } + + typedef my-bits { + type bits { + bit one; + bit two { + if-feature two; + } + bit three { + if-feature three; + } + } + } +} diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/invalid10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/invalid10.yang new file mode 100644 index 0000000000..026e9e3d8c --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6869/invalid10.yang @@ -0,0 +1,8 @@ +module foo { + namespace "foo"; + prefix foo; + + identity foo { + if-feature foo-identity; + } +} -- 2.36.6