Add StatementSupportNamespace 58/98758/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 30 Nov 2021 20:21:49 +0000 (21:21 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 30 Nov 2021 20:59:01 +0000 (21:59 +0100)
Expose StatementSupports registered for a particular root from a new
namespace, StatementSupportNamespace. SourceSpecificContext already has
all the knowledge and wiring required to make this work, so it is a
rather straightforward exercise.

This immediately allows us to loosen couplig betwen action/rpc and
input/output supports. Unfortunately choice/case coupling still remains
as we do not get a reference to the statement context in execution path.

JIRA: YANGTOOLS-1371
Change-Id: Iccf8fd394c5bf172cda73c820f1a483b04bbc7a4
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ImplicitParentAwareStatementSupport.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportNamespace.java [new file with mode: 0644]

index 79d8e3af5422567f96e75d80d82375a95b86ebcb..484f291a0929b75178e400bf2a7b1d820c881571 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementDefinitionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToModuleContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleCtx;
@@ -63,11 +64,37 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         FINISHED
     }
 
+    private static final class SupportedStatements
+            extends NamespaceBehaviour<QName, StatementSupport<?, ?, ?>, StatementSupportNamespace> {
+        private final QNameToStatementDefinitionMap statementDefinitions;
+
+        SupportedStatements(final QNameToStatementDefinitionMap statementDefinitions) {
+            super(StatementSupportNamespace.class);
+            this.statementDefinitions = requireNonNull(statementDefinitions);
+        }
+
+        @Override
+        public StatementSupport<?, ?, ?> getFrom(final NamespaceStorageNode storage, final QName key) {
+            return statementDefinitions.get(key);
+        }
+
+        @Override
+        public Map<QName, StatementSupport<?, ?, ?>> getAllFrom(final NamespaceStorageNode storage) {
+            throw new UnsupportedOperationException("StatementSupportNamespace is immutable");
+        }
+
+        @Override
+        public void addTo(final NamespaceStorageNode storage, final QName key, final StatementSupport<?, ?, ?> value) {
+            throw new UnsupportedOperationException("StatementSupportNamespace is immutable");
+        }
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(SourceSpecificContext.class);
 
     // TODO: consider keying by Byte equivalent of ExecutionOrder
     private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
     private final QNameToStatementDefinitionMap qnameToStmtDefMap = new QNameToStatementDefinitionMap();
+    private final SupportedStatements statementSupports = new SupportedStatements(qnameToStmtDefMap);
     private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
     private final @NonNull BuildGlobalContext globalContext;
 
@@ -253,8 +280,12 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public <K, V, N extends ParserNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
             final Class<N> type) {
+        if (StatementSupportNamespace.class.equals(type)) {
+            return (NamespaceBehaviour<K, V, N>) statementSupports;
+        }
         return globalContext.getNamespaceBehaviour(type);
     }
 
index 60ddd022e793d75256b9c72aa8823718cfbec97e..1d13c6b6690a23885b75724b280fec87289be450 100644 (file)
@@ -210,11 +210,6 @@ public final class RFC7950Reactors {
 
     private static StatementSupportBundle stmtDefBundle(final StatementSupportBundle linkageBundle,
             final YangParserConfiguration config) {
-        final InputStatementSupport rfc6020input = InputStatementSupport.rfc6020Instance(config);
-        final InputStatementSupport rfc7950input = InputStatementSupport.rfc7950Instance(config);
-        final OutputStatementSupport rfc6020output = OutputStatementSupport.rfc6020Instance(config);
-        final OutputStatementSupport rfc7950output = OutputStatementSupport.rfc7950Instance(config);
-
         return StatementSupportBundle.derivedFrom(linkageBundle)
             .addSupport(new YinElementStatementSupport(config))
             .addSupport(new ArgumentStatementSupport(config))
@@ -252,13 +247,13 @@ public final class RFC7950Reactors {
             .addVersionSpecificSupport(VERSION_1_1, ListStatementSupport.rfc7950Instance(config))
             .addSupport(ConfigListWarningNamespace.BEHAVIOUR)
             .addSupport(new UniqueStatementSupport(config))
-            .addVersionSpecificSupport(VERSION_1_1, new ActionStatementSupport(config, rfc7950input, rfc7950output))
-            .addVersionSpecificSupport(VERSION_1, new RpcStatementSupport(config, rfc6020input, rfc6020output))
-            .addVersionSpecificSupport(VERSION_1_1, new RpcStatementSupport(config, rfc7950input, rfc7950output))
-            .addVersionSpecificSupport(VERSION_1, rfc6020input)
-            .addVersionSpecificSupport(VERSION_1_1, rfc7950input)
-            .addVersionSpecificSupport(VERSION_1, rfc6020output)
-            .addVersionSpecificSupport(VERSION_1_1, rfc7950output)
+            .addVersionSpecificSupport(VERSION_1_1, new ActionStatementSupport(config))
+            .addVersionSpecificSupport(VERSION_1, new RpcStatementSupport(config))
+            .addVersionSpecificSupport(VERSION_1_1, new RpcStatementSupport(config))
+            .addVersionSpecificSupport(VERSION_1, InputStatementSupport.rfc6020Instance(config))
+            .addVersionSpecificSupport(VERSION_1_1, InputStatementSupport.rfc7950Instance(config))
+            .addVersionSpecificSupport(VERSION_1, OutputStatementSupport.rfc6020Instance(config))
+            .addVersionSpecificSupport(VERSION_1_1, OutputStatementSupport.rfc7950Instance(config))
             .addVersionSpecificSupport(VERSION_1, new NotificationStatementRFC6020Support(config))
             .addVersionSpecificSupport(VERSION_1_1, new NotificationStatementRFC7950Support(config))
             .addSupport(new FractionDigitsStatementSupport(config))
index ebf83b6b842455eb2ab61a48fbba63506cb5c00f..a788e8d074d71c47eeb280fed760f12a90f9ca9a 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.meta;
 
 import static com.google.common.base.Verify.verify;
-import static java.util.Objects.requireNonNull;
+import static com.google.common.base.Verify.verifyNotNull;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
@@ -30,6 +30,7 @@ import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingExcept
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractSchemaTreeStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportNamespace;
 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;
@@ -56,14 +57,8 @@ public final class ActionStatementSupport extends
             .addAny(YangStmtMapping.TYPEDEF)
             .build();
 
-    private final InputStatementSupport implicitInput;
-    private final OutputStatementSupport implicitOutput;
-
-    public ActionStatementSupport(final YangParserConfiguration config, final InputStatementSupport implicitInput,
-             final OutputStatementSupport implicitOutput) {
+    public ActionStatementSupport(final YangParserConfiguration config) {
         super(YangStmtMapping.ACTION, uninstantiatedPolicy(), config, SUBSTATEMENT_VALIDATOR);
-        this.implicitInput = requireNonNull(implicitInput);
-        this.implicitOutput = requireNonNull(implicitOutput);
     }
 
     @Override
@@ -86,10 +81,10 @@ public final class ActionStatementSupport extends
 
         verify(stmt instanceof StatementContextBase);
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, InputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implicitInput, null);
+            appendImplicitSubstatement(stmt, YangStmtMapping.INPUT.getStatementName());
         }
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, OutputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implicitOutput, null);
+            appendImplicitSubstatement(stmt, YangStmtMapping.OUTPUT.getStatementName());
         }
     }
 
@@ -125,4 +120,10 @@ public final class ActionStatementSupport extends
         return EffectiveStatements.copyAction(original, stmt.getArgument(),
             EffectiveStatementMixins.historyAndStatusFlags(stmt.history(), original.effectiveSubstatements()));
     }
+
+    private static void appendImplicitSubstatement(final Mutable<QName, ActionStatement, ActionEffectiveStatement> stmt,
+            final QName substatementName) {
+        ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
+            verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null);
+    }
 }
index d120c2c163216729a5f703a717db03d5c04a74eb..fdb89f81d88bbd96420c1744e2057ce4060cf1b7 100644 (file)
@@ -9,7 +9,7 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.meta;
 
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Verify.verify;
-import static java.util.Objects.requireNonNull;
+import static com.google.common.base.Verify.verifyNotNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
@@ -32,6 +32,7 @@ import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingExcept
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractSchemaTreeStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportNamespace;
 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;
@@ -53,14 +54,8 @@ public final class RpcStatementSupport extends AbstractSchemaTreeStatementSuppor
             .addAny(YangStmtMapping.TYPEDEF)
             .build();
 
-    private final InputStatementSupport implicitInput;
-    private final OutputStatementSupport implicitOutput;
-
-    public RpcStatementSupport(final YangParserConfiguration config, final InputStatementSupport implicitInput,
-            final OutputStatementSupport implicitOutput) {
+    public RpcStatementSupport(final YangParserConfiguration config) {
         super(YangStmtMapping.RPC, StatementPolicy.reject(), config, SUBSTATEMENT_VALIDATOR);
-        this.implicitInput = requireNonNull(implicitInput);
-        this.implicitOutput = requireNonNull(implicitOutput);
     }
 
     @Override
@@ -69,10 +64,10 @@ public final class RpcStatementSupport extends AbstractSchemaTreeStatementSuppor
 
         verify(stmt instanceof StatementContextBase);
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, InputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implicitInput, null);
+            appendImplicitSubstatement(stmt, YangStmtMapping.INPUT.getStatementName());
         }
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, OutputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implicitOutput, null);
+            appendImplicitSubstatement(stmt, YangStmtMapping.OUTPUT.getStatementName());
         }
     }
 
@@ -105,4 +100,10 @@ public final class RpcStatementSupport extends AbstractSchemaTreeStatementSuppor
                 .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
                 .toFlags();
     }
+
+    private static void appendImplicitSubstatement(final Mutable<QName, RpcStatement, RpcEffectiveStatement> stmt,
+            final QName substatementName) {
+        ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
+            verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null);
+    }
 }
index 0ca41292511fe66233797b9d0e71ff8016f2ad7e..73e0952cfa4954daf0a504b73802ee4c877c690b 100644 (file)
@@ -28,5 +28,6 @@ public interface ImplicitParentAwareStatementSupport {
      * @param stmtDef statement definition of substatement
      * @return optional of implicit parent statement support
      */
+    // FIXME: YANGTOOLS-1371: pass a NamespaceStmtCtx here, so choice/case can be decoupled
     Optional<StatementSupport<?, ?, ?>> getImplicitParentFor(StatementDefinition stmtDef);
 }
index d19812c3cf208bb61c5461d89cc4d34f1ea74014..fee21c432e9298e5a00dac15714789f18fd00c8b 100644 (file)
@@ -18,6 +18,21 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
  *
  * @author Robert Varga
  */
+// FIXME: 8.0.0: Fix naming and javadoc of this namespace.
+//
+// We have three competing namespaces dealing with various things and the interaction is no entirely clear:
+// - ExtensionNamespace, which is populated by ExtensionStatementSupport for all extensions with the corresponding
+//                       effective statement and used by SubstatementValidator
+// - StatementDefinitionNamespace (this), which is again populated by ExtensionStatementSupport to point to unrecognized
+//                                        statement support, i.e. preventing instantiation, and is used only by
+//                                        reactor's SourceSpecificContext
+// - StatementSupportNamespace, which is a virtual namespace providing access to StatementSupport instances for all
+//                              statements available in current processing phase of the source. It works as a union of
+//                              this namespace (StatementDefinitionNamespace) and the contents of
+//                              StatementSupportBundles.
+//
+// At the end of the day this feels like an under-utilized namespace: provided the contents of ExtensionNamespace and
+// StatementSupportBundles, SourceSpecificSpecificContext should be able to work its magic even without this namespace.
 @Beta
 public interface StatementDefinitionNamespace extends ParserNamespace<QName, StatementSupport<?, ?, ?>> {
     NamespaceBehaviour<QName, StatementSupport<?, ?, ?>, @NonNull StatementDefinitionNamespace> BEHAVIOUR =
diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportNamespace.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportNamespace.java
new file mode 100644 (file)
index 0000000..266a648
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.yang.parser.spi.meta;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Projection of {@link StatementSupport}s available within a particular source. This namespace is purely virtual and
+ * its behaviour corresponds to {@link NamespaceBehaviour#rootStatementLocal(Class)} and is always available. Its
+ * contents are derived from {@link StatementSupportBundle}s active in the current {@link ModelProcessingPhase} as well
+ * as {@link StatementDefinitionNamespace} and {@link StmtContext#yangVersion()} of the source root statement.
+ */
+@Beta
+public interface StatementSupportNamespace extends ParserNamespace<QName, StatementSupport<?, ?, ?>> {
+
+}