import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import com.google.common.collect.ImmutableList;
import java.util.Collection;
+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.parser.spi.meta.CopyHistory;
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.StatementSupport;
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
*/
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;
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) {
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);
- this.rawArgument = def.internArgument(rawArgument);
+ this.rawArgument = def.support().internArgument(rawArgument);
}
AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
final String rawArgument, final CopyType copyType) {
- super(def, CopyHistory.of(copyType, CopyHistory.original()));
+ super(def, copyType);
this.statementDeclSource = requireNonNull(ref);
this.rawArgument = rawArgument;
}
@Override
- public final Optional<StmtContext<?, ?, ?>> getOriginalCtx() {
+ public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
return Optional.empty();
}
@Override
- public final Optional<? extends StmtContext<?, ?, ?>> getPreviousCopyCtx() {
+ public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
return Optional.empty();
}
@Override
- public final StatementSourceReference getStatementSourceReference() {
+ public final StatementSourceReference sourceReference() {
return statementDeclSource;
}
@Override
- public final String rawStatementArgument() {
+ public final String rawArgument() {
return rawArgument;
}
@Override
public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
- return substatements.values();
+ 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 @NonNull StatementDefinition getDefinition() {
- return getPublicDefinition();
+ public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
+ effective = addEffectiveSubstatement(effective, substatement);
}
@Override
- public @NonNull StatementSourceReference getSourceReference() {
- return getStatementSourceReference();
+ final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
+ effective = addEffectiveSubstatementsImpl(effective, statements);
+ }
+
+ @Override
+ public final D declared() {
+ final D existing;
+ return (existing = declaredInstance) != null ? existing : loadDeclared();
+ }
+
+ private @NonNull D loadDeclared() {
+ final ModelProcessingPhase phase = getCompletedPhase();
+ checkState(phase == ModelProcessingPhase.FULL_DECLARATION || phase == ModelProcessingPhase.EFFECTIVE_MODEL,
+ "Cannot build declared instance after phase %s", phase);
+ return declaredInstance = definition().getFactory().createDeclared(this);
+ }
+
+ @Override
+ public StatementDefinition getDefinition() {
+ return publicDefinition();
+ }
+
+ @Override
+ public StatementSourceReference getSourceReference() {
+ return sourceReference();
}
@Override
final String argument) {
final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
- "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
+ "Declared statement cannot be added in effective phase at: %s", sourceReference());
final Optional<StatementSupport<?, ?, ?>> implicitParent =
definition().getImplicitParentFor(def.getPublicView());
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 Iterable<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
+ return effective;
+ }
+
+ @Override
+ final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamDeclared() {
+ return declaredSubstatements().stream().filter(StmtContext::isSupportedToBuildEffective);
+ }
+
+ @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);
+ }
+ substatements = null;
+ effective = null;
+ return count;
+ }
+
/**
* Lookup substatement by its offset in this statement.
*
final void walkChildren(final ModelProcessingPhase phase) {
checkState(isFullyDefined());
- substatements.values().forEach(stmt -> {
+ substatements.forEach(stmt -> {
stmt.walkChildren(phase);
stmt.endDeclared(phase);
});