X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=parser%2Fyang-parser-reactor%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FReactorStmtCtx.java;h=a00b5446e56db4d2fbfd566267cc50fec0fd18af;hb=a964a780e67e0f094f275a35c20a9079cb902a47;hp=66ad765afa84bc53301a1906773b6417186f2f21;hpb=0a8bdd5f4997e5f01decde68ddef7ac2c315e0f4;p=yangtools.git
diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java
index 66ad765afa..a00b5446e5 100644
--- a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java
+++ b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java
@@ -17,12 +17,13 @@ import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
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;
@@ -33,7 +34,9 @@ import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStatementState;
import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -41,12 +44,11 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.ExecutionOrder;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
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;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -118,7 +120,7 @@ abstract class ReactorStmtCtx, E extends Effec
* {@link #buildEffective()} instance. If this context is reused, it can be inflated to {@link EffectiveInstances}
* and also act as a common instance reuse site.
*/
- private @Nullable E effectiveInstance;
+ private @Nullable Object effectiveInstance;
// Master flag controlling whether this context can yield an effective statement
// FIXME: investigate the mechanics that are being supported by this, as it would be beneficial if we can get rid
@@ -160,11 +162,6 @@ abstract class ReactorStmtCtx, E extends Effec
// FIXME: move this out once we have JDK15+
private boolean boolFlag;
- // SchemaPath cache for use with SubstatementContext and InferredStatementContext. This hurts RootStatementContext
- // a bit in terms of size -- but those are only a few and SchemaPath is on its way out anyway.
- // FIXME: this should become 'QName'
- private SchemaPath schemaPath;
-
ReactorStmtCtx() {
// Empty on purpose
}
@@ -195,10 +192,10 @@ abstract class ReactorStmtCtx, E extends Effec
public abstract RootStatementContext, ?, ?> getRoot();
@Override
- public abstract Collection extends StatementContextBase, ?, ?>> mutableDeclaredSubstatements();
+ public abstract Collection extends @NonNull StatementContextBase, ?, ?>> mutableDeclaredSubstatements();
@Override
- public final @NonNull Registry getBehaviourRegistry() {
+ public final Registry getBehaviourRegistry() {
return getRoot().getBehaviourRegistryImpl();
}
@@ -239,13 +236,8 @@ abstract class ReactorStmtCtx, E extends Effec
@Override
public final QName moduleName() {
- final RootStatementContext, ?, ?> root = getRoot();
- return QName.create(StmtContextUtils.getRootModuleQName(root), root.getRawArgument());
- }
-
- @Override
- public final EffectiveStatement, ?> original() {
- return getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
+ final var root = getRoot();
+ return QName.create(StmtContextUtils.getModuleQName(root), root.getRawArgument());
}
//
@@ -258,17 +250,22 @@ abstract class ReactorStmtCtx, E extends Effec
@Override
public final > @NonNull Optional findSubstatementArgument(
final @NonNull Class type) {
- final E existing = effectiveInstance;
+ final E existing = effectiveInstance();
return existing != null ? existing.findFirstEffectiveSubstatementArgument(type)
: findSubstatementArgumentImpl(type);
}
@Override
public final boolean hasSubstatement(final @NonNull Class extends EffectiveStatement, ?>> type) {
- final E existing = effectiveInstance;
+ final E existing = effectiveInstance();
return existing != null ? existing.findFirstEffectiveSubstatement(type).isPresent() : hasSubstatementImpl(type);
}
+ private E effectiveInstance() {
+ final Object existing = effectiveInstance;
+ return existing != null ? EffectiveInstances.local(existing) : null;
+ }
+
// Visible due to InferredStatementContext's override. At this point we do not have an effective instance available.
> @NonNull Optional findSubstatementArgumentImpl(
final @NonNull Class type) {
@@ -297,22 +294,17 @@ abstract class ReactorStmtCtx, E extends Effec
}
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
- return toStringHelper.add("definition", definition()).add("rawArgument", rawArgument())
- .add("refCount", refString());
+ return toStringHelper.add("definition", definition()).add("argument", argument()).add("refCount", refString());
}
private String refString() {
final int current = refcount;
- switch (current) {
- case REFCOUNT_DEFUNCT:
- return "DEFUNCT";
- case REFCOUNT_SWEEPING:
- return "SWEEPING";
- case REFCOUNT_SWEPT:
- return "SWEPT";
- default:
- return String.valueOf(refcount);
- }
+ return switch (current) {
+ case REFCOUNT_DEFUNCT -> "DEFUNCT";
+ case REFCOUNT_SWEEPING -> "SWEEPING";
+ case REFCOUNT_SWEPT -> "SWEPT";
+ default -> String.valueOf(refcount);
+ };
}
/**
@@ -329,25 +321,22 @@ abstract class ReactorStmtCtx, E extends Effec
//
@Override
- public final > V namespaceItem(final Class<@NonNull N> type,
- final T key) {
+ public final V namespaceItem(final ParserNamespace type, final T key) {
return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, key);
}
@Override
- public final > Map namespace(final Class<@NonNull N> type) {
+ public final Map namespace(final ParserNamespace type) {
return getNamespace(type);
}
@Override
- public final >
- Map localNamespacePortion(final Class<@NonNull N> type) {
+ public final Map localNamespacePortion(final ParserNamespace type) {
return getLocalNamespace(type);
}
@Override
- protected > void onNamespaceElementAdded(final Class type, final K key,
- final V value) {
+ protected void onNamespaceElementAdded(final ParserNamespace type, final K key, final V value) {
// definition().onNamespaceElementAdded(this, type, key, value);
}
@@ -368,9 +357,11 @@ abstract class ReactorStmtCtx, E extends Effec
QNameModule targetModule);
@Override
- public final ReactorStmtCtx replicaAsChildOf(final Mutable, ?, ?> parent) {
+ public final ReplicaStatementContext replicaAsChildOf(final Mutable, ?, ?> parent) {
checkArgument(parent instanceof StatementContextBase, "Unsupported parent %s", parent);
- return replicaAsChildOf((StatementContextBase, ?, ?>) parent);
+ final var ret = replicaAsChildOf((StatementContextBase, ?, ?>) parent);
+ definition().onStatementAdded(ret);
+ return ret;
}
abstract @NonNull ReplicaStatementContext replicaAsChildOf(@NonNull StatementContextBase, ?, ?> parent);
@@ -383,17 +374,11 @@ abstract class ReactorStmtCtx, E extends Effec
@Override
public final E buildEffective() {
- final E existing;
- return (existing = effectiveInstance) != null ? existing : loadEffective();
+ final Object existing;
+ return (existing = effectiveInstance) != null ? EffectiveInstances.local(existing) : loadEffective();
}
private @NonNull E loadEffective() {
- // Creating an effective statement does not strictly require a declared instance -- there are statements like
- // 'input', which are implicitly defined.
- // Our implementation design makes an invariant assumption that buildDeclared() has been called by the time
- // we attempt to create effective statement:
- declared();
-
final E ret = createEffective();
effectiveInstance = ret;
// we have called createEffective(), substatements are no longer guarded by us. Let's see if we can clear up
@@ -406,6 +391,43 @@ abstract class ReactorStmtCtx, E extends Effec
abstract @NonNull E createEffective();
+ /**
+ * Routing of the request to build an effective statement from {@link InferredStatementContext} towards the original
+ * definition site. This is needed to pick the correct instantiation method: for declared statements we will
+ * eventually land in {@link AbstractResumedStatement}, for underclared statements that will be
+ * {@link UndeclaredStmtCtx}.
+ *
+ * @param factory Statement factory
+ * @param ctx Inferred statement context, i.e. where the effective statement is instantiated
+ * @return Built effective stateue
+ */
+ abstract @NonNull E createInferredEffective(@NonNull StatementFactory factory,
+ @NonNull InferredStatementContext ctx, Stream extends ReactorStmtCtx, ?, ?>> declared,
+ Stream extends ReactorStmtCtx, ?, ?>> effective);
+
+ /**
+ * Attach an effective copy of this statement. This essentially acts as a map, where we make a few assumptions:
+ *
+ * - {@code copy} and {@code this} statement share {@link #getOriginalCtx()} if it exists
+ * - {@code copy} did not modify any statements relative to {@code this}
+ *
+ *
+ * @param state effective statement state, acting as a lookup key
+ * @param stmt New copy to append
+ * @return {@code stmt} or a previously-created instances with the same {@code state}
+ */
+ @SuppressWarnings("unchecked")
+ final @NonNull E attachEffectiveCopy(final @NonNull EffectiveStatementState state, final @NonNull E stmt) {
+ final Object local = effectiveInstance;
+ final EffectiveInstances instances;
+ if (local instanceof EffectiveInstances) {
+ instances = (EffectiveInstances) local;
+ } else {
+ effectiveInstance = instances = new EffectiveInstances<>((E) local);
+ }
+ return instances.attachCopy(state, stmt);
+ }
+
/**
* Walk this statement's copy history and return the statement closest to original which has not had its effective
* statements modified. This statement and returned substatement logically have the same set of substatements, hence
@@ -443,14 +465,15 @@ abstract class ReactorStmtCtx, E extends Effec
//
//
+ // Non-final form ImplicitStmtCtx
@Override
- public final boolean isSupportedToBuildEffective() {
+ public boolean isSupportedToBuildEffective() {
return isSupportedToBuildEffective;
}
@Override
- public final void setIsSupportedToBuildEffective(final boolean isSupportedToBuildEffective) {
- this.isSupportedToBuildEffective = isSupportedToBuildEffective;
+ public final void setUnsupported() {
+ this.isSupportedToBuildEffective = false;
}
@Override
@@ -469,8 +492,8 @@ abstract class ReactorStmtCtx, E extends Effec
*/
if (isParentSupportedByFeatures()) {
// If the set of supported features has not been provided, all features are supported by default.
- final Set supportedFeatures = getFromNamespace(SupportedFeaturesNamespace.class,
- SupportedFeatures.SUPPORTED_FEATURES);
+ final Set supportedFeatures = getFromNamespace(ParserNamespaces.SUPPORTED_FEATURES,
+ Empty.value());
if (supportedFeatures == null || StmtContextUtils.checkFeatureSupport(this, supportedFeatures)) {
flags |= SET_SUPPORTED_BY_FEATURES;
return true;
@@ -614,63 +637,38 @@ abstract class ReactorStmtCtx, E extends Effec
@Override
public final QName argumentAsTypeQName() {
- return interpretAsQName(getRawArgument());
+ // FIXME: This may yield illegal argument exceptions
+ return StmtContextUtils.qnameFromArgument(getOriginalCtx().orElse(this), getRawArgument());
}
@Override
public final QNameModule effectiveNamespace() {
- // FIXME: there has to be a better way to do this
- return getSchemaPath().getLastComponent().getModule();
- }
-
- //
- //
- // Common SchemaPath cache. All of this is bound to be removed once YANGTOOLS-1066 is done.
- //
- //
-
- // Exists only to support {SubstatementContext,InferredStatementContext}.schemaPath()
- @Deprecated
- final @Nullable SchemaPath substatementGetSchemaPath() {
- if (schemaPath == null) {
- schemaPath = createSchemaPath((StatementContextBase, ?, ?>) coerceParentContext());
- }
- return schemaPath;
- }
-
- // FIXME: 7.0.0: this method's logic needs to be moved to the respective StatementSupport classes
- @Deprecated
- private SchemaPath createSchemaPath(final StatementContextBase, ?, ?> parent) {
- final SchemaPath parentPath = parent.getSchemaPath();
if (StmtContextUtils.isUnknownStatement(this)) {
- return parentPath.createChild(publicDefinition().getStatementName());
+ return publicDefinition().getStatementName().getModule();
+ }
+ if (producesDeclared(UsesStatement.class)) {
+ return coerceParent().effectiveNamespace();
}
- final Object argument = argument();
- if (argument instanceof QName) {
- final QName qname = (QName) argument;
- if (producesDeclared(UsesStatement.class)) {
- return parentPath;
- }
- return parentPath.createChild(qname);
+ final Object argument = argument();
+ if (argument instanceof QName qname) {
+ return qname.getModule();
}
- if (argument instanceof String) {
- return parentPath.createChild(interpretAsQName((String) argument));
+ if (argument instanceof String str) {
+ // FIXME: This may yield illegal argument exceptions
+ return StmtContextUtils.qnameFromArgument(getOriginalCtx().orElse(this), str).getModule();
}
- if (argument instanceof SchemaNodeIdentifier
+ if (argument instanceof SchemaNodeIdentifier sni
&& (producesDeclared(AugmentStatement.class) || producesDeclared(RefineStatement.class)
|| producesDeclared(DeviationStatement.class))) {
-
- return parentPath.createChild(((SchemaNodeIdentifier) argument).getNodeIdentifiers());
+ return sni.lastNodeIdentifier().getModule();
}
- // FIXME: this does not look right, investigate more?
- return parentPath;
+ return coerceParent().effectiveNamespace();
}
- private @NonNull QName interpretAsQName(final String argument) {
- // FIXME: This may yield illegal argument exceptions
- return StmtContextUtils.qnameFromArgument(getOriginalCtx().orElse(this), argument);
+ private ReactorStmtCtx, ?, ?> coerceParent() {
+ return (ReactorStmtCtx, ?, ?>) coerceParentContext();
}
//
@@ -823,6 +821,10 @@ abstract class ReactorStmtCtx, E extends Effec
}
// Propagate towards parent if there is one
+ sweepParent();
+ }
+
+ private void sweepParent() {
final ReactorStmtCtx, ?, ?> parent = getParentContext();
if (parent != null) {
parent.sweepOnChildDecrement();
@@ -846,12 +848,9 @@ abstract class ReactorStmtCtx, E extends Effec
// parent is potentially reclaimable
if (noParentRef()) {
- LOG.trace("Cleanup {} of parent {}", refcount, this);
+ LOG.trace("Cleanup {} of parent {}", refs, this);
if (sweepState()) {
- final ReactorStmtCtx, ?, ?> parent = getParentContext();
- if (parent != null) {
- parent.sweepOnChildDecrement();
- }
+ sweepParent();
}
}
}