Add OnDemandSchemaTreeStorageNode 30/93530/1
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 29 Oct 2020 11:55:55 +0000 (12:55 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 31 Oct 2020 08:04:48 +0000 (09:04 +0100)
In order to correctly implement schema dependencies, we need to
invoke a callback from namespace prerequisites back to
StatementContextBase and its subclasses.

The conduit here is NamespaceBehavior.getFrom(), which is invoked
with a namespace key. For ChildSchemaNodeNamespace this ends up
the QName matching the argument the corresponding
SchemaTreeEffectiveStatement will end up having.

Introduce OnDemandSchemaTreeStorageNode, which acts as an extension
to normal NamespaceStorageNode behavior -- it allows an
implementation to supply a QName-based child statement to be
returned.

Since StatementContextBase is a NamespaceStorageNode, its subclasses
can now additionally implement this interface to receive the
callback.

JIRA: YANGTOOLS-784
Change-Id: I0e6f621eb39b341af61005b2334174e814c18875
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 5be3107a8f7daca1e3584bace9a684e21315df70)

yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java

index fe9c4e58c9c72ed37671d8d92fa23fad14eb8315..7c972fa38e03f0455ad0df04e8b18188d8ea2728 100644 (file)
@@ -28,9 +28,8 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
  */
 @Beta
 public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
-    extends NamespaceBehaviour<QName, StmtContext<?, D, E>, ChildSchemaNodeNamespace<D, E>>
-    implements StatementNamespace<QName, D, E> {
-
+        extends NamespaceBehaviour<QName, StmtContext<?, D, E>, ChildSchemaNodeNamespace<D, E>>
+        implements StatementNamespace<QName, D, E> {
     public ChildSchemaNodeNamespace() {
         super((Class) ChildSchemaNodeNamespace.class);
     }
@@ -43,7 +42,19 @@ public final class ChildSchemaNodeNamespace<D extends DeclaredStatement<QName>,
 
     @Override
     public StmtContext<?, D, E> getFrom(final NamespaceStorageNode storage, final QName key) {
-        return globalOrStatementSpecific(storage).getFromLocalStorage(getIdentifier(), key);
+        // Get the backing storage node for the requested storage
+        final NamespaceStorageNode storageNode = globalOrStatementSpecific(storage);
+        // Check try to look up existing node
+        final StmtContext<?, D, E> existing = storageNode.getFromLocalStorage(getIdentifier(), key);
+
+        // An existing node takes precedence, if it does not exist try to request it
+        return existing != null ? existing : requestFrom(storageNode, key);
+    }
+
+    private static <D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
+            StmtContext<?, D, E> requestFrom(final NamespaceStorageNode storageNode, final QName key) {
+        return storageNode instanceof OnDemandSchemaTreeStorageNode
+            ? ((OnDemandSchemaTreeStorageNode) storageNode).requestSchemaTreeChild(key) : null;
     }
 
     @Override
index 86b687d917052ee5d312fe880ab924d9fb5f2e4a..2139cd55623debd712cb18efb8a2eeeb3d00b7d8 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Verify;
 import java.util.Map;
@@ -17,6 +18,9 @@ import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
+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;
 
 /**
@@ -107,6 +111,30 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
                 V value);
     }
 
+    /**
+     * Interface implemented by {@link NamespaceStorageNode}s which support dynamic addition of child elements as they
+     * are requested. This means that such a node can, defer creation of child namespace storage nodes, in effect lazily
+     * expanding this namespace on an if-needed basis.
+     */
+    @Beta
+    public interface OnDemandSchemaTreeStorageNode extends NamespaceStorageNode {
+        /**
+         * Request that a new member of this node's schema tree statement be added. Implementations are required to
+         * perform lookup in their internal structure and create a child if tracktable. Resulting node is expected to
+         * have been registered with local storage, so that it is accessible through
+         * {@link #getFromLocalStorage(Class, Object)}.
+         *
+         * <p>
+         * 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.
+         *
+         * @param qname node identifier of the child being requested
+         * @return Requested child, if it is present.
+         */
+        <D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
+            @Nullable StmtContext<QName, D, E> requestSchemaTreeChild(QName qname);
+    }
+
     protected NamespaceBehaviour(final Class<N> identifier) {
         super(identifier);
     }