Graduate ChildSchemaNodeNamespace as SchemaTreeNamespace 52/93652/1
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 5 Nov 2020 16:16:01 +0000 (17:16 +0100)
committerRobert Varga <nite@hq.sk>
Thu, 12 Nov 2020 11:19:37 +0000 (11:19 +0000)
This is a @Beta construct in yang-parser-rfc7950, but it provides
a crucial link between statements and namespaces.

In terms of semantic change, this is a direct replacement for the SPI
idea that there is a SchemaNodeIdentifierNamespace. While that namespace
allowed lookup based on SchemaNodeIdentifier, while
SchemaTreeNamespace follows QName addressing -- i.e. we are changing
the addressing mode and allowing more flexible walks.

This is a strictly speaking API-breaking change, but since it enables
reactor/parser-rfc7950 interactions and is allowed under @Beta API
change rules, we will backport this to otherwise stable branches.

Existence of this namespace allows us to neatly tie it with
OnDemandSchemaTreeStorageNode.

JIRA: YANGTOOLS-1168
Change-Id: I9b1c30d21f7021d4c21f3e5a519f6cd1539871ad
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 6682a8e2a8c02ed7a66bddb8b7a86009ffbbb98d)

yang/odlext-parser-support/src/main/java/org/opendaylight/yangtools/odlext/parser/AnyxmlStatementSupportOverride.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/BaseSchemaTreeStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementSupport.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/SchemaNodeIdentifierNamespace.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/SchemaTreeNamespace.java [moved from yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java with 77% similarity]
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java

index 4aa9c8453ecd03629f4af22fd4029c7b7ef2a73b..e7f52455f29e30794efe20621638d0e5f884c6fb 100644 (file)
@@ -18,8 +18,8 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.anyxml.AnyxmlStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ForwardingStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
@@ -70,7 +70,7 @@ public final class AnyxmlStatementSupportOverride
     private static Optional<ContainerSchemaNode> getAnyXmlSchema(
             final StmtContext<QName, AnyxmlStatement, AnyxmlEffectiveStatement> ctx,
             final SchemaNodeIdentifier contentSchemaPath) {
-        return ChildSchemaNodeNamespace.findNode(ctx.getRoot(), contentSchemaPath)
+        return SchemaTreeNamespace.findNode(ctx.getRoot(), contentSchemaPath)
                 .map(StmtContext::buildEffective)
                 .filter(ContainerSchemaNode.class::isInstance).map(ContainerSchemaNode.class::cast);
     }
index b4c9ee540453decbfadcaebd8a2d7a6e5da31e61..7bac557ebe7d16e1c36101ea28d1552520c319eb 100644 (file)
@@ -16,7 +16,6 @@ import com.google.common.collect.Sets;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.parser.openconfig.stmt.OpenConfigVersionSupport;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.YangNamespaceContextNamespace;
@@ -120,6 +119,7 @@ import org.opendaylight.yangtools.yang.parser.spi.IdentityNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
 import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.SubmoduleNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
@@ -218,7 +218,7 @@ public final class RFC7950Reactors {
             .addSupport(YinElementStatementSupport.getInstance())
             .addSupport(ArgumentStatementSupport.getInstance())
             .addSupport(ExtensionStatementSupport.getInstance())
-            .addSupport(new ChildSchemaNodeNamespace<>())
+            .addSupport(SchemaTreeNamespace.getInstance())
             .addSupport(ExtensionNamespace.BEHAVIOUR)
             .addSupport(TypedefStatementSupport.getInstance())
             .addSupport(TypeNamespace.BEHAVIOUR)
index 0d180264f33f6a662dfa01ed20069ce70658dc53..2bb06827d9ad61fc9431b8d408b6f52c0ef3f8ef 100644 (file)
@@ -11,13 +11,14 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 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.StmtContextUtils;
 
 /**
- * Specialization of {@link BaseQNameStatementSupport} for stating the onStatementAdded method.
+ * Specialization of {@link BaseQNameStatementSupport} for {@link SchemaTreeEffectiveStatement} implementations. Every
+ * statement automatically participates in {@link SchemaTreeNamespace}.
  *
  * @param <D> Declared Statement representation
  * @param <E> Effective Statement representation
@@ -34,7 +35,7 @@ public abstract class BaseSchemaTreeStatementSupport<D extends DeclaredStatement
 
     @Override
     public final void onStatementAdded(final Mutable<QName, D, E> stmt) {
-        stmt.coerceParentContext().addToNs(ChildSchemaNodeNamespace.class, stmt.coerceStatementArgument(), stmt);
+        stmt.coerceParentContext().addToNs(SchemaTreeNamespace.class, stmt.coerceStatementArgument(), stmt);
     }
 
     // Non-final because {@code input} and {@code output} are doing their own thing.
index abbd44738770cd42d137a034ae3e80c52a610b73..5c85334c3cdaf196a7fe16bf0e9df12f60de89f7 100644 (file)
@@ -33,10 +33,10 @@ import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.ArgumentUtils;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -91,7 +91,7 @@ abstract class AbstractAugmentStatementSupport
         final ModelActionBuilder augmentAction = augmentNode.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
         augmentAction.requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL);
         final Prerequisite<Mutable<?, ?, EffectiveStatement<?, ?>>> target = augmentAction.mutatesEffectiveCtxPath(
-            getSearchRoot(augmentNode), ChildSchemaNodeNamespace.class,
+            getSearchRoot(augmentNode), SchemaTreeNamespace.class,
             augmentNode.coerceStatementArgument().getNodeIdentifiers());
 
         augmentAction.apply(new InferenceAction() {
@@ -131,7 +131,7 @@ abstract class AbstractAugmentStatementSupport
                  */
                 if (YangStmtMapping.USES == augmentNode.coerceParentContext().getPublicDefinition()) {
                     final SchemaNodeIdentifier augmentArg = augmentNode.coerceStatementArgument();
-                    final Optional<StmtContext<?, ?, ?>> targetNode = ChildSchemaNodeNamespace.findNode(
+                    final Optional<StmtContext<?, ?, ?>> targetNode = SchemaTreeNamespace.findNode(
                         getSearchRoot(augmentNode), augmentArg);
                     if (targetNode.isPresent() && StmtContextUtils.isUnknownStatement(targetNode.get())) {
                         augmentNode.setIsSupportedToBuildEffective(false);
index a809ad5a6e256c5b5f2b823b55ce5fd299e2a1e3..0ce5325f848f971f04407e14e38b9785717a435a 100644 (file)
@@ -28,9 +28,9 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.DeviateEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DeviateStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -130,7 +130,7 @@ abstract class AbstractDeviateStatementSupport
 
         final Prerequisite<Mutable<?, ?, EffectiveStatement<?, ?>>> targetCtxPrerequisite =
                 deviateAction.mutatesEffectiveCtxPath(deviateStmtCtx.getRoot(),
-                    ChildSchemaNodeNamespace.class, deviationTarget.getNodeIdentifiers());
+                    SchemaTreeNamespace.class, deviationTarget.getNodeIdentifiers());
 
         deviateAction.apply(new InferenceAction() {
             @Override
index 73e682c9de5305fdcc691de129913ced3f406563..c260f2888b27b4cacbba33f9d7129bb13aa31710 100644 (file)
@@ -33,11 +33,11 @@ import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Desce
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.refine.RefineEffectiveStatementImpl;
 import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -301,7 +301,7 @@ public final class UsesStatementSupport
             subStmtCtx.getStatementSourceReference(),
             "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument);
 
-        final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = ChildSchemaNodeNamespace.findNode(
+        final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = SchemaTreeNamespace.findNode(
             usesParentCtx, (SchemaNodeIdentifier) refineArgument);
         InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.getStatementSourceReference(),
             "Refine target node %s not found.", refineArgument);
index cbed70ad848d6532e661447d83e0c003cd56fb3d..eadda2e485f9a8a79e1bef409215b30a206ed296 100644 (file)
@@ -20,7 +20,10 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace.TreeBa
  * <p>
  * This namespace is scoped to the parent node or module, unless the parent node is a case node. In that case,
  * the namespace is scoped to the closest ancestor node that is not a case or choice node.
+ *
+ * @deprecated This namespace was never implemented. Its purpose is generalized in {@link SchemaTreeNamespace}.
  */
+@Deprecated(forRemoval = true)
 public interface SchemaNodeIdentifierNamespace
     extends TreeBased<SchemaNodeIdentifier, DeclaredStatement<?>, EffectiveStatement<?, DeclaredStatement<?>>> {
 
@@ -5,17 +5,20 @@
  * 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.rfc7950.namespace;
+package org.opendaylight.yangtools.yang.parser.spi;
 
 import com.google.common.annotations.Beta;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 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.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
@@ -24,22 +27,41 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 /**
- * Statement local namespace, which holds direct schema node descendants.
+ * Statement local namespace, which holds direct schema node descendants. This corresponds to the contents of the schema
+ * tree as exposed through {@link SchemaTreeAwareEffectiveStatement}.
  */
+// FIXME: 7.0.0: this contract seems to fall on the reactor side of things rather than parser-spi. Consider moving this
+//               into yang-(parser-)reactor-api.
 @Beta
-public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
-        extends NamespaceBehaviour<QName, StmtContext<?, D, E>, ChildSchemaNodeNamespace<D, E>>
+public final class SchemaTreeNamespace<D extends DeclaredStatement<QName>,
+            E extends SchemaTreeEffectiveStatement<D>>
+        extends NamespaceBehaviour<QName, StmtContext<?, D, E>, SchemaTreeNamespace<D, E>>
         implements StatementNamespace<QName, D, E> {
-    public ChildSchemaNodeNamespace() {
-        super((Class) ChildSchemaNodeNamespace.class);
+    private static final @NonNull SchemaTreeNamespace<?, ?> INSTANCE = new SchemaTreeNamespace<>();
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private SchemaTreeNamespace() {
+        super((Class) SchemaTreeNamespace.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <D extends DeclaredStatement<QName>, E extends SchemaTreeEffectiveStatement<D>>
+            @NonNull SchemaTreeNamespace<D, E> getInstance() {
+        return (SchemaTreeNamespace<D, E>) INSTANCE;
     }
 
     @Override
     public StmtContext<?, D, E> get(final QName key) {
-        // TODO Auto-generated method stub
+        // FIXME: 7.0.0: this method needs to be well-defined
         return null;
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * This method is analogous to {@link SchemaTreeAwareEffectiveStatement#findSchemaTreeNode(QName)}.
+     */
     @Override
     public StmtContext<?, D, E> getFrom(final NamespaceStorageNode storage, final QName key) {
         // Get the backing storage node for the requested storage
@@ -59,7 +81,7 @@ public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>,
 
     @Override
     public Map<QName, StmtContext<?, D, E>> getAllFrom(final NamespaceStorageNode storage) {
-        // TODO Auto-generated method stub
+        // FIXME: 7.0.0: this method needs to be well-defined
         return null;
     }
 
@@ -67,7 +89,7 @@ public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>,
     @Override
     public void addTo(final NamespaceStorageNode storage, final QName key, final StmtContext<?, D, E> value) {
         final StmtContext<?, D, E> prev = globalOrStatementSpecific(storage).putToLocalStorageIfAbsent(
-            ChildSchemaNodeNamespace.class, key, value);
+            SchemaTreeNamespace.class, key, value);
 
         if (prev != null) {
             throw new SourceException(value.getStatementSourceReference(),
@@ -95,7 +117,7 @@ public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>,
 
         QName nextPath = iterator.next();
         @SuppressWarnings("unchecked")
-        StmtContext<?, ?, ?> current = (StmtContext<?, ?, ?>) root.getFromNamespace(ChildSchemaNodeNamespace.class,
+        StmtContext<?, ?, ?> current = (StmtContext<?, ?, ?>) root.getFromNamespace(SchemaTreeNamespace.class,
             nextPath);
         if (current == null) {
             return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), root));
@@ -104,7 +126,7 @@ public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>,
             nextPath = iterator.next();
             @SuppressWarnings("unchecked")
             final StmtContext<?, ?, ?> nextNodeCtx = (StmtContext<?, ?, ?>) current.getFromNamespace(
-                ChildSchemaNodeNamespace.class, nextPath);
+                SchemaTreeNamespace.class, nextPath);
             if (nextNodeCtx == null) {
                 return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), current));
             }
index 577c59c2909a0ea4a45258c52ea23e263a5a81a4..25d440954780cc5cd9b2f7105718d9ea7d6f62ac 100644 (file)
@@ -22,6 +22,8 @@ import org.opendaylight.yangtools.yang.common.QName;
 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.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 
 /**
  * Definition / implementation of specific Identifier Namespace behaviour. A namespace behaviour is built on top
@@ -128,8 +130,14 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
          * This method must not change its mind about a child's presence -- once it returns non-present, it has to be
          * always returning non-present.
          *
+         * <p>
+         * The results produced by this method are expected to be consistent with
+         * {@link SchemaTreeAwareEffectiveStatement#findSchemaTreeNode(QName)} and
+         * {@link SchemaTreeNamespace#getFrom(NamespaceStorageNode, QName)}.
+         *
          * @param qname node identifier of the child being requested
          * @return Requested child, if it is present.
+         * @throws NullPointerException in {@code qname} is null
          */
         <D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
             @Nullable StmtContext<QName, D, E> requestSchemaTreeChild(QName qname);