Add support for yang-ext:mount extension 99/96499/1
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Jun 2021 09:40:27 +0000 (11:40 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Jun 2021 11:54:58 +0000 (13:54 +0200)
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 <robert.varga@pantheon.tech>
model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountEffectiveStatement.java [new file with mode: 0644]
model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/MountStatement.java [new file with mode: 0644]
model/odlext-model-api/src/main/java/org/opendaylight/yangtools/odlext/model/api/OpenDaylightExtensionsStatements.java
parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountEffectiveStatementImpl.java [new file with mode: 0644]
parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementImpl.java [new file with mode: 0644]
parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/MountStatementSupport.java [new file with mode: 0644]
parser/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/RefMountStatement.java [new file with mode: 0644]
parser/odlext-parser-support/src/test/java/org/opendaylight/yangtools/odlext/parser/MountTest.java [new file with mode: 0644]
parser/odlext-parser-support/src/test/resources/mount.yang [new file with mode: 0644]
parser/odlext-parser-support/src/test/resources/yang-ext.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 (file)
index 0000000..8428a9a
--- /dev/null
@@ -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<Empty, MountStatement> {
+    @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 (file)
index 0000000..457739d
--- /dev/null
@@ -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<Empty> {
+    @Override
+    default StatementDefinition statementDefinition() {
+        return OpenDaylightExtensionsStatements.MOUNT;
+    }
+}
index f6f53f6910b6c28dc532de58cd4825c7a5cbef77..821a9239ef1f693c95e788e4b7af177606e55afd 100644 (file)
@@ -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<? 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);
     }
@@ -56,7 +60,7 @@ public enum OpenDaylightExtensionsStatements implements StatementDefinition {
 
     @Override
     public Optional<ArgumentDefinition> 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 (file)
index 0000000..b57c222
--- /dev/null
@@ -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<Empty, MountStatement>
+        implements MountEffectiveStatement {
+    MountEffectiveStatementImpl(final MountStatement declared,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> 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 (file)
index 0000000..ca1d61e
--- /dev/null
@@ -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<? extends DeclaredStatement<?>> 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 (file)
index 0000000..6cbcae1
--- /dev/null
@@ -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<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);
+    }
+}
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 (file)
index 0000000..bec0900
--- /dev/null
@@ -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<Empty, MountStatement> 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 (file)
index 0000000..17a0559
--- /dev/null
@@ -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<MountEffectiveStatement> 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 (file)
index 0000000..73600d7
--- /dev/null
@@ -0,0 +1,12 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  import yang-ext {
+    prefix ext;
+  }
+
+  container foo {
+    ext:mount;
+  }
+}
index 2d89e616b5fd33ba72d0c32a10a92403032e46ef..f53148adc89eb953e0d97f0ba8091d15ca5033ae 100644 (file)
@@ -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