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.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.ModelActionBuilder;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @param <E> Effective Statement representation
*/
abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
- extends NamespaceStorageSupport implements Mutable<A, D, E>, Current<A, D> {
+ extends AbstractNamespaceStorage implements Mutable<A, D, E>, Current<A, D> {
private static final Logger LOG = LoggerFactory.getLogger(ReactorStmtCtx.class);
/**
// hence improve memory layout.
private byte flags;
- // Flag for use by AbstractResumedStatement, ReplicaStatementContext and InferredStatementContext. Each of them
- // uses it to indicated a different condition. This is hiding in the alignment shadow created by
- // 'isSupportedToBuildEffective'.
- // FIXME: move this out once we have JDK15+
- private boolean boolFlag;
-
ReactorStmtCtx() {
// Empty on purpose
}
ReactorStmtCtx(final ReactorStmtCtx<A, D, E> original) {
isSupportedToBuildEffective = original.isSupportedToBuildEffective;
- boolFlag = original.boolFlag;
flags = original.flags;
}
// Used by ReplicaStatementContext only
ReactorStmtCtx(final ReactorStmtCtx<A, D, E> original, final Void dummy) {
- boolFlag = isSupportedToBuildEffective = original.isSupportedToBuildEffective;
+ isSupportedToBuildEffective = original.isSupportedToBuildEffective;
flags = original.flags;
}
public abstract Collection<? extends @NonNull StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements();
@Override
- public final Registry getBehaviourRegistry() {
- return getRoot().getBehaviourRegistryImpl();
+ final <K, V> NamespaceAccess<K, V> accessNamespace(final ParserNamespace<K, V> type) {
+ return getRoot().getSourceContext().accessNamespace(type);
}
@Override
@Override
public final QName moduleName() {
- final RootStatementContext<?, ?, ?> root = getRoot();
- return QName.create(StmtContextUtils.getRootModuleQName(root), root.getRawArgument());
+ final var root = getRoot();
+ return QName.create(StmtContextUtils.getModuleQName(root), root.getRawArgument());
}
//
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);
+ };
}
/**
//
//
- // NamespaceStorageSupport/Mutable integration methods. Keep these together.
+ // AbstractNamespaceStorage/Mutable integration methods. Keep these together.
//
//
@Override
- public final <K, V, T extends K, N extends ParserNamespace<K, V>> V namespaceItem(final Class<@NonNull N> type,
- final T key) {
- return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, key);
+ public StorageType getStorageType() {
+ // Common to all subclasses except RootStatementContext
+ return StorageType.STATEMENT_LOCAL;
+ }
+
+ @Override
+ public final <K, V> V namespaceItem(final ParserNamespace<K, V> namespace, final K key) {
+ return accessNamespace(namespace).valueFrom(this, key);
}
@Override
- public final <K, V, N extends ParserNamespace<K, V>> Map<K, V> namespace(final Class<@NonNull N> type) {
- return getNamespace(type);
+ public final <K, V> Map<K, V> namespace(final ParserNamespace<K, V> namespace) {
+ return getNamespace(namespace);
}
@Override
- public final <K, V, N extends ParserNamespace<K, V>>
- Map<K, V> localNamespacePortion(final Class<@NonNull N> type) {
- return getLocalNamespace(type);
+ public final <K, V> Map<K, V> localNamespacePortion(final ParserNamespace<K, V> namespace) {
+ return getLocalNamespace(namespace);
}
@Override
- protected <K, V, N extends ParserNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key,
- final V value) {
+ protected <K, V> void onNamespaceElementAdded(final ParserNamespace<K, V> type, final K key, final V value) {
// definition().onNamespaceElementAdded(this, type, key, value);
}
* @return Built effective stateue
*/
abstract @NonNull E createInferredEffective(@NonNull StatementFactory<A, D, E> factory,
- @NonNull InferredStatementContext<A, D, E> ctx, Stream<? extends StmtContext<?, ?, ?>> declared,
- Stream<? extends StmtContext<?, ?, ?>> effective);
+ @NonNull InferredStatementContext<A, D, E> 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:
//
//
+ // Non-final for ImplicitStmtCtx/InferredStatementContext
@Override
- public final boolean isSupportedToBuildEffective() {
+ public boolean isSupportedToBuildEffective() {
return isSupportedToBuildEffective;
}
@Override
public final void setUnsupported() {
- this.isSupportedToBuildEffective = false;
+ isSupportedToBuildEffective = false;
}
@Override
*/
if (isParentSupportedByFeatures()) {
// If the set of supported features has not been provided, all features are supported by default.
- final Set<QName> supportedFeatures = getFromNamespace(SupportedFeaturesNamespace.class, Empty.value());
+ final var supportedFeatures = namespaceItem(ParserNamespaces.SUPPORTED_FEATURES, Empty.value());
if (supportedFeatures == null || StmtContextUtils.checkFeatureSupport(this, supportedFeatures)) {
flags |= SET_SUPPORTED_BY_FEATURES;
return true;
return false;
}
- // These two exist only due to memory optimization, should live in AbstractResumedStatement.
- final boolean fullyDefined() {
- return boolFlag;
- }
-
- final void setFullyDefined() {
- boolFlag = true;
- }
-
- // This exists only due to memory optimization, should live in ReplicaStatementContext. In this context the flag
- // indicates the need to drop source's reference count when we are being swept.
- final boolean haveSourceReference() {
- return boolFlag;
- }
-
- // These three exist due to memory optimization, should live in InferredStatementContext. In this context the flag
- // indicates whether or not this statement's substatement file was modified, i.e. it is not quite the same as the
- // prototype's file.
- final boolean isModified() {
- return boolFlag;
- }
-
- final void setModified() {
- boolFlag = true;
- }
-
- final void setUnmodified() {
- boolFlag = false;
- }
-
// These two exist only for StatementContextBase. Since we are squeezed for size, with only a single bit available
// in flags, we default to 'false' and only set the flag to true when we are absolutely sure -- and all other cases
// err on the side of caution by taking the time to evaluate each substatement separately.
}
final Object argument = argument();
- if (argument instanceof QName) {
- return ((QName) argument).getModule();
+ if (argument instanceof QName qname) {
+ return qname.getModule();
}
- if (argument instanceof String) {
+ if (argument instanceof String str) {
// FIXME: This may yield illegal argument exceptions
- return StmtContextUtils.qnameFromArgument(getOriginalCtx().orElse(this), (String) argument).getModule();
+ 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 ((SchemaNodeIdentifier) argument).lastNodeIdentifier().getModule();
+ return sni.lastNodeIdentifier().getModule();
}
return coerceParent().effectiveNamespace();
private byte calculateParentRefcount() {
final ReactorStmtCtx<?, ?, ?> parent = getParentContext();
- if (parent == null) {
- return PARENTREF_ABSENT;
- }
+ return parent == null ? PARENTREF_ABSENT : parent.refcountForChild();
+ }
+ private byte refcountForChild() {
// A slight wrinkle here is that our machinery handles only PRESENT -> ABSENT invalidation and we can reach here
// while inference is still ongoing and hence we may not have a complete picture about existing references. We
// could therefore end up caching an ABSENT result and then that information becoming stale as a new reference
// is introduced.
- if (parent.executionOrder() < ExecutionOrder.EFFECTIVE_MODEL) {
+ if (executionOrder() < ExecutionOrder.EFFECTIVE_MODEL) {
return PARENTREF_UNKNOWN;
}
// There are three possibilities:
- // - REFCOUNT_NONE, in which case we need to search next parent
+ // - REFCOUNT_NONE, in which case we need to check if this statement or its parents are holding a reference
// - negative (< REFCOUNT_NONE), meaning parent is in some stage of sweeping, hence it does not have
// a reference to us
// - positive (> REFCOUNT_NONE), meaning parent has an explicit refcount which is holding us down
- final int refs = parent.refcount;
+ final int refs = refcount;
if (refs == REFCOUNT_NONE) {
- return parent.parentRefcount();
+ return noImplictRef() && noParentRef() ? PARENTREF_ABSENT : PARENTREF_PRESENT;
}
return refs < REFCOUNT_NONE ? PARENTREF_ABSENT : PARENTREF_PRESENT;
}