--- /dev/null
+/*
+ * 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<Empty, MountStatement> {
+ @Override
+ default StatementDefinition statementDefinition() {
+ return OpenDaylightExtensionsStatements.MOUNT;
+ }
+}
--- /dev/null
+/*
+ * 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<Empty> {
+ @Override
+ default StatementDefinition statementDefinition() {
+ return OpenDaylightExtensionsStatements.MOUNT;
+ }
+}
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;
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),
RPC_CONTEXT_REFERENCE(QName.create(OpenDaylightExtensionsConstants.ORIGINAL_MODULE, "rpc-context-reference"),
"context-type", RpcContextReferenceStatement.class, RpcContextReferenceEffectiveStatement.class);
- private final Class<? extends EffectiveStatement<?, ?>> effectiveRepresentation;
- private final Class<? extends DeclaredStatement<?>> declaredRepresentation;
- private final QName statementName;
+ private final @NonNull Class<? extends EffectiveStatement<?, ?>> effectiveRepresentation;
+ private final @NonNull Class<? extends DeclaredStatement<?>> declaredRepresentation;
+ private final @NonNull QName statementName;
private final ArgumentDefinition argumentDef;
OpenDaylightExtensionsStatements(final QName statementName, final String argumentName,
final Class<? extends DeclaredStatement<?>> declaredRepresentation,
final Class<? extends EffectiveStatement<?, ?>> 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);
}
@Override
public Optional<ArgumentDefinition> getArgumentDefinition() {
- return Optional.of(argumentDef);
+ return Optional.ofNullable(argumentDef);
}
@Override
--- /dev/null
+/*
+ * 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<Empty, MountStatement>
+ implements MountEffectiveStatement {
+ MountEffectiveStatementImpl(final MountStatement declared,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared, substatements);
+ }
+}
--- /dev/null
+/*
+ * 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<? extends DeclaredStatement<?>> substatements) {
+ super(substatements);
+ }
+}
--- /dev/null
+/*
+ * 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<MountStatement, MountEffectiveStatement> {
+ private static final SubstatementValidator VALIDATOR =
+ SubstatementValidator.builder(OpenDaylightExtensionsStatements.MOUNT).build();
+ private static final Set<StatementDefinition> 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<Empty, MountStatement, MountEffectiveStatement> 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<Empty, MountStatement, ?> ctx,
+ final ImmutableList<? extends DeclaredStatement<?>> 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<Empty, MountStatement> stmt,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ return new MountEffectiveStatementImpl(stmt.declared(), substatements);
+ }
+}
--- /dev/null
+/*
+ * 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<Empty, MountStatement> implements MountStatement {
+ RefMountStatement(final MountStatement delegate, final DeclarationReference ref) {
+ super(delegate, ref);
+ }
+}
--- /dev/null
+/*
+ * 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<MountEffectiveStatement> mount = foo.findDataTreeNode(QName.create(FOO, "foo")).orElseThrow()
+ .findFirstEffectiveSubstatement(MountEffectiveStatement.class);
+ assertTrue(mount.isPresent());
+ }
+}
--- /dev/null
+module foo {
+ namespace foo;
+ prefix foo;
+
+ import yang-ext {
+ prefix ext;
+ }
+
+ container foo {
+ ext:mount;
+ }
+}
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