From 9de5d1c8a51215c7d9c995a904692ce806268655 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 9 Jun 2021 11:40:27 +0200 Subject: [PATCH] Add support for yang-ext:mount extension We have a legacy 'mount' extension which we do not support in the parser, make sure we define its model and recognize it. JIRA: YANGTOOLS-1294 Change-Id: Icd31ae6264cff4dbf3554e8a1e4cd97d9788f317 Signed-off-by: Robert Varga --- .../model/api/MountEffectiveStatement.java | 21 ++++++ .../odlext/model/api/MountStatement.java | 21 ++++++ .../api/OpenDaylightExtensionsStatements.java | 18 +++-- .../parser/MountEffectiveStatementImpl.java | 23 +++++++ .../odlext/parser/MountStatementImpl.java | 19 ++++++ .../odlext/parser/MountStatementSupport.java | 66 +++++++++++++++++++ .../odlext/parser/RefMountStatement.java | 19 ++++++ .../yangtools/odlext/parser/MountTest.java | 59 +++++++++++++++++ .../src/test/resources/mount.yang | 12 ++++ .../src/test/resources/yang-ext.yang | 33 ++++++++++ 10 files changed, 284 insertions(+), 7 deletions(-) create mode 100644 model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountEffectiveStatement.java create mode 100644 model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountStatement.java create mode 100644 parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountEffectiveStatementImpl.java create mode 100644 parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementImpl.java create mode 100644 parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementSupport.java create mode 100644 parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/RefMountStatement.java create mode 100644 parser/odlext-parser-support/src/test/java/org/opendaylight/yangtools/odlext/parser/MountTest.java create mode 100644 parser/odlext-parser-support/src/test/resources/mount.yang diff --git a/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountEffectiveStatement.java b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountEffectiveStatement.java new file mode 100644 index 0000000000..8428a9a882 --- /dev/null +++ b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountEffectiveStatement.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.model.api; + +import com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.model.api.stmt.UnknownEffectiveStatement; + +@Beta +public interface MountEffectiveStatement extends UnknownEffectiveStatement { + @Override + default StatementDefinition statementDefinition() { + return OpenDaylightExtensionsStatements.MOUNT; + } +} diff --git a/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountStatement.java b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountStatement.java new file mode 100644 index 0000000000..457739d5c2 --- /dev/null +++ b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountStatement.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.model.api; + +import com.google.common.annotations.Beta; +import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement; + +@Beta +public interface MountStatement extends UnknownStatement { + @Override + default StatementDefinition statementDefinition() { + return OpenDaylightExtensionsStatements.MOUNT; + } +} diff --git a/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/OpenDaylightExtensionsStatements.java b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/OpenDaylightExtensionsStatements.java index f6f53f6910..821a9239ef 100644 --- a/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/OpenDaylightExtensionsStatements.java +++ b/model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/OpenDaylightExtensionsStatements.java @@ -11,7 +11,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import java.util.Optional; -import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.ArgumentDefinition; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; @@ -19,12 +19,15 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; @Beta -@NonNullByDefault public enum OpenDaylightExtensionsStatements implements StatementDefinition { // Binding codegen support AUGMENT_IDENTIFIER(QName.create(OpenDaylightExtensionsConstants.ORIGINAL_MODULE, "augment-identifier"), "identifier", AugmentIdentifierStatement.class, AugmentIdentifierEffectiveStatement.class), + // Mount extension + MOUNT(QName.create(OpenDaylightExtensionsConstants.ORIGINAL_MODULE, "mount"), null, + MountStatement.class, MountEffectiveStatement.class), + // Context-aware RPCs CONTEXT_INSTANCE(QName.create(OpenDaylightExtensionsConstants.ORIGINAL_MODULE, "context-instance"), "context-type", ContextInstanceStatement.class, ContextInstanceEffectiveStatement.class), @@ -35,16 +38,17 @@ public enum OpenDaylightExtensionsStatements implements StatementDefinition { RPC_CONTEXT_REFERENCE(QName.create(OpenDaylightExtensionsConstants.ORIGINAL_MODULE, "rpc-context-reference"), "context-type", RpcContextReferenceStatement.class, RpcContextReferenceEffectiveStatement.class); - private final Class> effectiveRepresentation; - private final Class> declaredRepresentation; - private final QName statementName; + private final @NonNull Class> effectiveRepresentation; + private final @NonNull Class> declaredRepresentation; + private final @NonNull QName statementName; private final ArgumentDefinition argumentDef; OpenDaylightExtensionsStatements(final QName statementName, final String argumentName, final Class> declaredRepresentation, final Class> effectiveRepresentation) { this.statementName = statementName.intern(); - this.argumentDef = ArgumentDefinition.of(QName.create(statementName, argumentName).intern(), false); + this.argumentDef = argumentName == null ? null + : ArgumentDefinition.of(QName.create(statementName, argumentName).intern(), false); this.declaredRepresentation = requireNonNull(declaredRepresentation); this.effectiveRepresentation = requireNonNull(effectiveRepresentation); } @@ -56,7 +60,7 @@ public enum OpenDaylightExtensionsStatements implements StatementDefinition { @Override public Optional getArgumentDefinition() { - return Optional.of(argumentDef); + return Optional.ofNullable(argumentDef); } @Override diff --git a/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountEffectiveStatementImpl.java b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountEffectiveStatementImpl.java new file mode 100644 index 0000000000..b57c2223e0 --- /dev/null +++ b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountEffectiveStatementImpl.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.parser; + +import com.google.common.collect.ImmutableList; +import org.opendaylight.yangtools.odlext.model.api.MountEffectiveStatement; +import org.opendaylight.yangtools.odlext.model.api.MountStatement; +import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; +import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement.DefaultArgument.WithSubstatements; + +final class MountEffectiveStatementImpl extends WithSubstatements + implements MountEffectiveStatement { + MountEffectiveStatementImpl(final MountStatement declared, + final ImmutableList> substatements) { + super(declared, substatements); + } +} diff --git a/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementImpl.java b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementImpl.java new file mode 100644 index 0000000000..ca1d61e6dd --- /dev/null +++ b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementImpl.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.parser; + +import com.google.common.collect.ImmutableList; +import org.opendaylight.yangtools.odlext.model.api.MountStatement; +import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; +import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithoutArgument.WithSubstatements; + +final class MountStatementImpl extends WithSubstatements implements MountStatement { + MountStatementImpl(final ImmutableList> substatements) { + super(substatements); + } +} diff --git a/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementSupport.java b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementSupport.java new file mode 100644 index 0000000000..6cbcae111b --- /dev/null +++ b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementSupport.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.parser; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableList; +import java.util.Set; +import org.opendaylight.yangtools.odlext.model.api.MountEffectiveStatement; +import org.opendaylight.yangtools.odlext.model.api.MountStatement; +import org.opendaylight.yangtools.odlext.model.api.OpenDaylightExtensionsStatements; +import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; +import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference; +import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; +import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration; +import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractEmptyStatementSupport; +import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; + +@Beta +public final class MountStatementSupport + extends AbstractEmptyStatementSupport { + private static final SubstatementValidator VALIDATOR = + SubstatementValidator.builder(OpenDaylightExtensionsStatements.MOUNT).build(); + private static final Set ALLOWED_PARENTS = + Set.of(YangStmtMapping.CONTAINER, YangStmtMapping.LIST); + + public MountStatementSupport(final YangParserConfiguration config) { + super(OpenDaylightExtensionsStatements.MOUNT, StatementPolicy.exactReplica(), config, VALIDATOR); + } + + @Override + public void onStatementAdded(final Mutable stmt) { + final StatementDefinition parentDef = stmt.coerceParentContext().publicDefinition(); + SourceException.throwIf(!ALLOWED_PARENTS.contains(parentDef), stmt, + "Mount is allowed only under container or list, not %s", parentDef); + } + + @Override + protected MountStatement createDeclared(final StmtContext ctx, + final ImmutableList> substatements) { + return new MountStatementImpl(substatements); + } + + @Override + protected MountStatement attachDeclarationReference(final MountStatement stmt, + final DeclarationReference reference) { + return new RefMountStatement(stmt, reference); + } + + @Override + protected MountEffectiveStatement createEffective(final Current stmt, + final ImmutableList> substatements) { + return new MountEffectiveStatementImpl(stmt.declared(), substatements); + } +} diff --git a/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/RefMountStatement.java b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/RefMountStatement.java new file mode 100644 index 0000000000..bec0900a73 --- /dev/null +++ b/parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/RefMountStatement.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.parser; + +import org.opendaylight.yangtools.odlext.model.api.MountStatement; +import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference; +import org.opendaylight.yangtools.yang.model.spi.meta.AbstractRefStatement; + +final class RefMountStatement extends AbstractRefStatement implements MountStatement { + RefMountStatement(final MountStatement delegate, final DeclarationReference ref) { + super(delegate, ref); + } +} diff --git a/parser/odlext-parser-support/src/test/java/org/opendaylight/yangtools/odlext/parser/MountTest.java b/parser/odlext-parser-support/src/test/java/org/opendaylight/yangtools/odlext/parser/MountTest.java new file mode 100644 index 0000000000..17a0559514 --- /dev/null +++ b/parser/odlext-parser-support/src/test/java/org/opendaylight/yangtools/odlext/parser/MountTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.odlext.parser; + +import static org.junit.Assert.assertTrue; + +import java.util.Optional; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.yangtools.odlext.model.api.MountEffectiveStatement; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.XMLNamespace; +import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; +import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration; +import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors; +import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource; +import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; + +public class MountTest { + private static final QNameModule FOO = QNameModule.create(XMLNamespace.of("foo")); + + private static CrossSourceStatementReactor reactor; + + @BeforeClass + public static void createReactor() { + reactor = RFC7950Reactors.vanillaReactorBuilder() + .addStatementSupport(ModelProcessingPhase.FULL_DECLARATION, + new MountStatementSupport(YangParserConfiguration.DEFAULT)) + .build(); + } + + @AfterClass + public static void freeReactor() { + reactor = null; + } + + @Test + public void test() throws Exception { + final ModuleEffectiveStatement foo = reactor.newBuild() + .addSource(YangStatementStreamSource.create(YangTextSchemaSource.forResource("/yang-ext.yang"))) + .addSource(YangStatementStreamSource.create(YangTextSchemaSource.forResource("/mount.yang"))) + .buildEffective() + .getModuleStatements() + .get(FOO); + + final Optional mount = foo.findDataTreeNode(QName.create(FOO, "foo")).orElseThrow() + .findFirstEffectiveSubstatement(MountEffectiveStatement.class); + assertTrue(mount.isPresent()); + } +} diff --git a/parser/odlext-parser-support/src/test/resources/mount.yang b/parser/odlext-parser-support/src/test/resources/mount.yang new file mode 100644 index 0000000000..73600d7010 --- /dev/null +++ b/parser/odlext-parser-support/src/test/resources/mount.yang @@ -0,0 +1,12 @@ +module foo { + namespace foo; + prefix foo; + + import yang-ext { + prefix ext; + } + + container foo { + ext:mount; + } +} diff --git a/parser/odlext-parser-support/src/test/resources/yang-ext.yang b/parser/odlext-parser-support/src/test/resources/yang-ext.yang index 2d89e616b5..f53148adc8 100644 --- a/parser/odlext-parser-support/src/test/resources/yang-ext.yang +++ b/parser/odlext-parser-support/src/test/resources/yang-ext.yang @@ -42,6 +42,39 @@ module yang-ext { argument "identifier"; } + // Mount point marker + + extension mount { + description + "YANG language extension which marks a place where a semantic mount + point can be present. This extension can only be used in a container or + a list statement, for example: + + module foo { + container foo { + leaf bar { + type string; + } + + ext:mount; + } + } + + In this example, container foo can contain a local leaf bar and some + mounted data. From addressing perspective, the extension use acts as + a container with yang-ext's namespace, i.e. it looks as though as this + (yang-ext) module contained the following construct: + + import foo { prefix foo; } + + augment /foo:foo { + container mount; + } + + From data lifecycle perspective, this container should never be + automatically included in the datastore content for 'container foo', unless + specifically explicitly requested."; + } // Context-aware RPCs -- 2.36.6