import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ImmutableList;
import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
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;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
* @param <E> Effective Statement representation
*/
abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
- extends StatementContextBase<A, D, E> implements ResumedStatement {
- private static final Logger LOG = LoggerFactory.getLogger(AbstractResumedStatement.class);
-
- private final @NonNull StatementSourceReference statementDeclSource;
+ extends OriginalStmtCtx<A, D, E> implements ResumedStatement {
private final String rawArgument;
- private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
private StatementMap substatements = StatementMap.empty();
private @Nullable D declaredInstance;
// Copy constructor
AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
super(original);
- this.statementDeclSource = original.statementDeclSource;
this.rawArgument = original.rawArgument;
this.substatements = original.substatements;
this.declaredInstance = original.declaredInstance;
AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
final String rawArgument) {
- super(def);
- this.statementDeclSource = requireNonNull(ref);
+ super(def, ref);
this.rawArgument = def.support().internArgument(rawArgument);
}
- AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
- final String rawArgument, final CopyType copyType) {
- super(def, copyType);
- this.statementDeclSource = requireNonNull(ref);
- this.rawArgument = rawArgument;
- }
-
- @Override
- public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
- return Optional.empty();
- }
-
- @Override
- public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
- return Optional.empty();
- }
-
- @Override
- public final StatementSourceReference sourceReference() {
- return statementDeclSource;
- }
-
@Override
public final String rawArgument() {
return rawArgument;
}
@Override
- public final Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
- return substatements;
- }
-
- @Override
- public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
- return mutableEffectiveSubstatements(effective);
- }
-
- @Override
- public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
- effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
- }
-
- @Override
- public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
- final String statementArg) {
- effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
- }
-
- @Override
- public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
- effective = addEffectiveSubstatement(effective, substatement);
- }
-
- @Override
- final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
- effective = addEffectiveSubstatementsImpl(effective, statements);
+ public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
+ return verifyNotNull(substatements);
}
@Override
return declaredInstance = definition().getFactory().createDeclared(this, substatementsAsDeclared());
}
+ @SuppressWarnings({ "rawtypes", "unchecked" })
private @NonNull Stream<DeclaredStatement<?>> substatementsAsDeclared() {
- // FIXME: YANGTOOLS-1383: this stream includes implicit case statements, but it should not
- return substatements.stream().map(AbstractResumedStatement::declared);
+ final Stream<AbstractResumedStatement<?, ?, ?>> stream;
+ if (getImplicitDeclaredFlag()) {
+ stream = substatements.stream().map(AbstractResumedStatement::unmaskUndeclared);
+ } else {
+ stream = (Stream) substatements.stream();
+ }
+
+ return stream.map(AbstractResumedStatement::declared);
}
@Override
@Override
public final StatementSourceReference getSourceReference() {
- return statementDeclSource;
+ return sourceReference();
}
@Override
return fullyDefined();
}
+ @Override
+ final E createEffective(final StatementFactory<A, D, E> factory) {
+ return createEffective(factory, this, streamDeclared(), streamEffective());
+ }
+
+ // Creates EffectiveStatement through full materialization and assumes declared statement presence
+ private @NonNull E createEffective(final StatementFactory<A, D, E> factory,
+ final StatementContextBase<A, D, E> ctx, final Stream<? extends StmtContext<?, ?, ?>> declared,
+ final Stream<? extends StmtContext<?, ?, ?>> effective) {
+ // Statement reference count infrastructure makes an assumption that effective statement is only built after
+ // the declared statement is already done. Statements tracked by this class always have a declared view, and
+ // we need to ensure that is built before we touch effective substatements.
+ //
+ // Once the effective substatement stream has been exhausted, reference counting will triggers a sweep, hence
+ // the substatements may be gone by the time the factory attempts to acquire the declared statement.
+ ctx.declared();
+
+ return factory.createEffective(ctx, declared, effective);
+ }
+
+ @Override
+ final E createInferredEffective(final StatementFactory<A, D, E> factory,
+ final InferredStatementContext<A, D, E> ctx, final Stream<? extends StmtContext<?, ?, ?>> declared,
+ final Stream<? extends StmtContext<?, ?, ?>> effective) {
+ return createEffective(factory, ctx, declared, effective);
+ }
+
/**
* Create a new substatement at the specified offset.
*
checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
"Declared statement cannot be added in effective phase at: %s", sourceReference());
+ final SubstatementContext<X, Y, Z> ret;
final var implicitParent = definition().getImplicitParentFor(this, def.getPublicView());
if (implicitParent.isPresent()) {
- return createImplicitParent(offset, implicitParent.orElseThrow(), ref, argument)
- .createSubstatement(0, def, ref, argument);
+ setImplicitDeclaredFlag();
+ final var parent = createUndeclared(offset, implicitParent.orElseThrow(), ref, argument);
+ ret = new SubstatementContext<>(parent, def, ref, argument);
+ parent.addEffectiveSubstatement(ret);
+ } else {
+ ret = new SubstatementContext<>(this, def, ref, argument);
+ substatements = substatements.put(offset, ret);
}
- final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
- substatements = substatements.put(offset, ret);
def.onStatementAdded(ret);
return ret;
}
- @Override
- final AbstractResumedStatement<A, D, E> unmodifiedEffectiveSource() {
- // This statement is comes from the source
- return this;
- }
-
- @Override
- final boolean hasEmptySubstatements() {
- return substatements.size() == 0 && effective.isEmpty();
- }
-
- @Override
- final boolean noSensitiveSubstatements() {
- return hasEmptySubstatements()
- || noSensitiveSubstatements(substatements) && noSensitiveSubstatements(effective);
- }
-
- @Override
- final Iterator<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
- return effective.iterator();
+ private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
+ UndeclaredStmtCtx<X, Y, Z> createUndeclared(final int offset, final StatementSupport<X, Y, Z> support,
+ final StatementSourceReference ref, final String argument) {
+ final UndeclaredStmtCtx<X, Y, Z> ret;
+ final var implicitParent = definition().getImplicitParentFor(this, support.getPublicView());
+ if (implicitParent.isPresent()) {
+ final var parent = createUndeclared(offset, implicitParent.orElseThrow(), ref, argument);
+ ret = new ImplicitStmtCtx<>(parent, support, argument);
+ parent.addEffectiveSubstatement(ret);
+ } else {
+ ret = new ImplicitStmtCtx<>(this, support, argument);
+ substatements = substatements.put(offset, ret);
+ }
+ support.onStatementAdded(ret);
+ return ret;
}
@Override
}
@Override
- final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
- return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
- }
-
- @Override
- final void markNoParentRef() {
- markNoParentRef(substatements);
- markNoParentRef(effective);
- }
-
- @Override
- final int sweepSubstatements() {
- // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
- // - 'effective' member sweeping a 'substatements' member
- // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
- // We then iterate once again, counting what remains unswept
- sweep(substatements);
- sweep(effective);
- final int count = countUnswept(substatements) + countUnswept(effective);
- if (count != 0) {
- LOG.debug("{} children left to sweep from {}", count, this);
- }
+ final void dropDeclaredSubstatements() {
substatements = null;
- effective = null;
- return count;
}
/**
* @return Substatement, or null if substatement does not exist.
*/
final @Nullable AbstractResumedStatement<?, ?, ?> enterSubstatement(final int offset) {
- var ret = substatements.get(offset);
- if (ret != null) {
- while (ret.origin() == StatementOrigin.CONTEXT) {
- ret = verifyNotNull(ret.substatements.get(0));
- }
+ final var stmt = substatements.get(offset);
+ return stmt == null ? null : unmaskUndeclared(stmt);
+ }
+
+ private static @NonNull AbstractResumedStatement<?, ?, ?> unmaskUndeclared(final ReactorStmtCtx<?, ?, ?> stmt) {
+ var ret = stmt;
+ while (!(ret instanceof AbstractResumedStatement)) {
+ verify(ret instanceof UndeclaredStmtCtx, "Unexpectred statement %s", ret);
+ ret = ((UndeclaredStmtCtx<?, ?, ?>) ret).getResumedSubstatement();
}
- return ret;
+ return (AbstractResumedStatement<?, ?, ?>) ret;
}
/**
var ret = verifyParent(parent);
// Unwind all undeclared statements
- while (ret.origin() == StatementOrigin.CONTEXT) {
+ while (!(ret instanceof AbstractResumedStatement)) {
ret.finishDeclaration(phase);
ret = verifyParent(ret.getParentContext());
}
- return ret;
+ return (AbstractResumedStatement<?, ?, ?>) ret;
}
- // FIXME: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would remove the
- // need for this method. In ordered to do that we need to untangle SubstatementContext's users and do not
- // allow it being reparent()ed.
- private static AbstractResumedStatement<?, ?, ?> verifyParent(final StatementContextBase<?, ?, ?> parent) {
- verify(parent instanceof AbstractResumedStatement, "Unexpected parent context %s", parent);
- return (AbstractResumedStatement<?, ?, ?>) parent;
+ // FIXME: AbstractResumedStatement should only ever have OriginalStmtCtx parents, which would remove the need for
+ // this method. In ordered to do that we need to untangle SubstatementContext's users and do not allow it
+ // being reparent()ed.
+ private static OriginalStmtCtx<?, ?, ?> verifyParent(final StatementContextBase<?, ?, ?> parent) {
+ verify(parent instanceof OriginalStmtCtx, "Unexpected parent context %s", parent);
+ return (OriginalStmtCtx<?, ?, ?>) parent;
}
final void resizeSubstatements(final int expectedSize) {
substatements = substatements.ensureCapacity(expectedSize);
}
+ @Override
final void declarationFinished(final ModelProcessingPhase phase) {
finishChildrenDeclaration(phase);
finishDeclaration(phase);
checkState(isFullyDefined());
substatements.forEach(stmt -> stmt.declarationFinished(phase));
}
-
- /**
- * Ends declared section of current node for the specified phase.
- *
- * @param phase processing phase that ended
- */
- private void finishDeclaration(final ModelProcessingPhase phase) {
- definition().onDeclarationFinished(this, phase);
- }
-
- private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
- final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
- return createSubstatement(offset, new StatementDefinitionContext<>(implicitParent),
- ImplicitSubstatement.of(ref), argument);
- }
}