From 1e03bcd72c6de996d3c15a6a7ef6a780a774db73 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Wed, 14 Dec 2016 10:59:10 +0100 Subject: [PATCH] Bug 6880: [Yang 1.1] Allow leaf-lists to have default values Allow leaf-lists to have default values in Yang 1.1 models. Change-Id: I84df558e886eb695e83686e972f5cb9e1086b061 Signed-off-by: Peter Kajsa --- .../stmt/rfc6020/LeafListStatementImpl.java | 6 ++ .../stmt/rfc6020/YangInferencePipeline.java | 4 +- .../LeafListEffectiveStatementImpl.java | 17 +++++- .../LeafListStatementRfc7950Support.java | 41 +++++++++++++ .../yang/parser/stmt/rfc7950/Bug6880Test.java | 59 +++++++++++++++++++ .../test/resources/rfc7950/bug6880/foo.yang | 11 ++++ .../resources/rfc7950/bug6880/invalid10.yang | 10 ++++ 7 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/LeafListStatementRfc7950Support.java create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6880Test.java create mode 100644 yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/foo.yang create mode 100644 yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/invalid10.yang diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LeafListStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LeafListStatementImpl.java index f050ead658..0453fe0402 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LeafListStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LeafListStatementImpl.java @@ -14,6 +14,7 @@ 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.ConfigStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.DefaultStatement; 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.LeafListStatement; @@ -130,6 +131,11 @@ public class LeafListStatementImpl extends AbstractDeclaredStatement return firstDeclared(StatusStatement.class); } + @Override + public final Collection getDefaults() { + return allDeclared(DefaultStatement.class); + } + @Nullable @Override public DescriptionStatement getDescription() { 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 2e8585bf11..ece5944347 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 @@ -73,6 +73,7 @@ import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.IdentityStatementRfc7 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; +import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.LeafListStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ListStatementRfc7950Support; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ModifierStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ModuleStatementRfc7950Support; @@ -211,7 +212,8 @@ public final class YangInferencePipeline { .addSupport(treeScoped(GroupingNamespace.class)) //treeScoped .addSupport(new ErrorMessageStatementImpl.Definition()) .addSupport(new ErrorAppTagStatementImpl.Definition()) - .addSupport(new LeafListStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1, new LeafListStatementImpl.Definition()) + .addVersionSpecificSupport(VERSION_1_1, new LeafListStatementRfc7950Support()) .addSupport(new PresenceStatementImpl.Definition()) .addSupport(new KeyStatementImpl.Definition()) .addSupport(new MaxElementsStatementImpl.Definition()) diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/LeafListEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/LeafListEffectiveStatementImpl.java index de1322110d..176c9c5bbc 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/LeafListEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/LeafListEffectiveStatementImpl.java @@ -8,6 +8,9 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import java.util.Collection; +import java.util.List; import java.util.Objects; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode; @@ -28,6 +31,7 @@ public final class LeafListEffectiveStatementImpl extends AbstractEffectiveDataS private final TypeDefinition type; private final LeafListSchemaNode original; private final boolean userOrdered; + private final List defaultValues; public LeafListEffectiveStatementImpl( final StmtContext> ctx) { @@ -41,14 +45,15 @@ public final class LeafListEffectiveStatementImpl extends AbstractEffectiveDataS final ConcreteTypeBuilder builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(), ctx.getSchemaPath().get()); + final ImmutableList.Builder defaultValuesBuilder = ImmutableList.builder(); boolean isUserOrdered = false; - for (EffectiveStatement stmt : effectiveSubstatements()) { + for (final EffectiveStatement stmt : effectiveSubstatements()) { if (stmt instanceof OrderedByEffectiveStatementImpl) { isUserOrdered = ORDER_BY_USER_KEYWORD.equals(stmt.argument()); } if (stmt instanceof DefaultEffectiveStatementImpl) { - builder.setDefaultValue(stmt.argument()); + defaultValuesBuilder.add(((DefaultEffectiveStatementImpl) stmt).argument()); } else if (stmt instanceof DescriptionEffectiveStatementImpl) { builder.setDescription(((DescriptionEffectiveStatementImpl)stmt).argument()); } else if (stmt instanceof ReferenceEffectiveStatementImpl) { @@ -60,10 +65,16 @@ public final class LeafListEffectiveStatementImpl extends AbstractEffectiveDataS } } + defaultValues = defaultValuesBuilder.build(); type = builder.build(); userOrdered = isUserOrdered; } + @Override + public Collection getDefaults() { + return defaultValues; + } + @Override public Optional getOriginal() { return Optional.fromNullable(original); @@ -99,7 +110,7 @@ public final class LeafListEffectiveStatementImpl extends AbstractEffectiveDataS if (getClass() != obj.getClass()) { return false; } - LeafListEffectiveStatementImpl other = (LeafListEffectiveStatementImpl) obj; + final LeafListEffectiveStatementImpl other = (LeafListEffectiveStatementImpl) obj; return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath()); } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/LeafListStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/LeafListStatementRfc7950Support.java new file mode 100644 index 0000000000..1fdc4da1f4 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/LeafListStatementRfc7950Support.java @@ -0,0 +1,41 @@ +/* + * 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.LeafListStatementImpl; + +/** + * Class providing necessary support for processing YANG 1.1 leaf-list statement. + */ +@Beta +public class LeafListStatementRfc7950Support extends LeafListStatementImpl.Definition { + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping + .LEAF_LIST) + .addOptional(YangStmtMapping.CONFIG) + .addAny(YangStmtMapping.DEFAULT) + .addOptional(YangStmtMapping.DESCRIPTION) + .addAny(YangStmtMapping.IF_FEATURE) + .addOptional(YangStmtMapping.MIN_ELEMENTS) + .addOptional(YangStmtMapping.MAX_ELEMENTS) + .addAny(YangStmtMapping.MUST) + .addOptional(YangStmtMapping.ORDERED_BY) + .addOptional(YangStmtMapping.REFERENCE) + .addOptional(YangStmtMapping.STATUS) + .addMandatory(YangStmtMapping.TYPE) + .addOptional(YangStmtMapping.UNITS) + .addOptional(YangStmtMapping.WHEN) + .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/Bug6880Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6880Test.java new file mode 100644 index 0000000000..b08c141c95 --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6880Test.java @@ -0,0 +1,59 @@ +/* + * 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.util.Collection; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +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 Bug6880Test { + private static final String FOO_NS = "foo"; + private static final String FOO_REV = "1970-01-01"; + + @Test + public void valid10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException { + final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6880/foo.yang"); + assertNotNull(schemaContext); + + final SchemaNode findDataSchemaNode = SchemaContextUtil.findDataSchemaNode(schemaContext, + SchemaPath.create(true, QName.create(FOO_NS, FOO_REV, "my-leaf-list"))); + assertTrue(findDataSchemaNode instanceof LeafListSchemaNode); + final LeafListSchemaNode myLeafList = (LeafListSchemaNode) findDataSchemaNode; + + final Collection defaults = myLeafList.getDefaults(); + assertEquals(2, defaults.size()); + assertTrue(defaults.contains("my-default-value-1") && defaults.contains("my-default-value-2")); + } + + @Test + public void invalid10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException { + try { + StmtTestUtils.parseYangSource("/rfc7950/bug6880/invalid10.yang"); + fail("Test should fail due to invalid Yang 1.0"); + } catch (final SomeModifiersUnresolvedException e) { + assertTrue(e.getCause().getMessage().startsWith("DEFAULT is not valid for LEAF_LIST")); + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/foo.yang new file mode 100644 index 0000000000..cbfae8822d --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/foo.yang @@ -0,0 +1,11 @@ +module foo { + namespace "foo"; + prefix foo; + yang-version 1.1; + + leaf-list my-leaf-list { + type string; + default "my-default-value-1"; + default "my-default-value-2"; + } +} diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/invalid10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/invalid10.yang new file mode 100644 index 0000000000..e52780d155 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6880/invalid10.yang @@ -0,0 +1,10 @@ +module foo { + namespace "foo"; + prefix foo; + + leaf-list my-leaf-list { + type string; + default "my-default-value-1"; + default "my-default-value-2"; + } +} -- 2.36.6