From 125814abf2d77b54d466fe6ee5e421100e5cd406 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 30 Nov 2021 21:21:49 +0100 Subject: [PATCH] Add StatementSupportNamespace 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 --- .../stmt/reactor/SourceSpecificContext.java | 31 +++++++++++++++++++ .../rfc7950/reactor/RFC7950Reactors.java | 19 +++++------- .../stmt/meta/ActionStatementSupport.java | 21 +++++++------ .../stmt/meta/RpcStatementSupport.java | 21 +++++++------ .../ImplicitParentAwareStatementSupport.java | 1 + .../meta/StatementDefinitionNamespace.java | 15 +++++++++ .../spi/meta/StatementSupportNamespace.java | 22 +++++++++++++ 7 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportNamespace.java diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java index 79d8e3af54..484f291a09 100644 --- a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java +++ b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java @@ -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, 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> 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 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 > NamespaceBehaviour getNamespaceBehaviour( final Class type) { + if (StatementSupportNamespace.class.equals(type)) { + return (NamespaceBehaviour) statementSupports; + } return globalContext.getNamespaceBehaviour(type); } diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java index 60ddd022e7..1d13c6b669 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java @@ -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)) diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java index ebf83b6b84..a788e8d074 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java @@ -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 stmt, + final QName substatementName) { + ((StatementContextBase) stmt).appendImplicitSubstatement( + verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null); + } } diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java index d120c2c163..fdb89f81d8 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java @@ -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 stmt, + final QName substatementName) { + ((StatementContextBase) stmt).appendImplicitSubstatement( + verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null); + } } diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ImplicitParentAwareStatementSupport.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ImplicitParentAwareStatementSupport.java index 0ca4129251..73e0952cfa 100644 --- a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ImplicitParentAwareStatementSupport.java +++ b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ImplicitParentAwareStatementSupport.java @@ -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> getImplicitParentFor(StatementDefinition stmtDef); } diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java index d19812c3cf..fee21c432e 100644 --- a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java +++ b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java @@ -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> { NamespaceBehaviour, @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 index 0000000000..266a6480bb --- /dev/null +++ b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportNamespace.java @@ -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> { + +} -- 2.36.6