*/
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
+import static com.google.common.base.Preconditions.checkArgument;
+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 java.util.Optional;
-import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
private final ModelProcessingPhase phase;
private final SourceSpecificContext ctx;
- private StatementContextBase<?, ?, ?> current;
+ private AbstractResumedStatement<?, ?, ?> current;
StatementContextWriter(final SourceSpecificContext ctx, final ModelProcessingPhase phase) {
- this.ctx = Preconditions.checkNotNull(ctx);
- this.phase = Preconditions.checkNotNull(phase);
+ this.ctx = requireNonNull(ctx);
+ this.phase = requireNonNull(phase);
}
@Override
public Optional<? extends ResumedStatement> resumeStatement(final int childId) {
- final Optional<StatementContextBase<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
- existing.ifPresent(this::resumeStatement);
- return existing;
+ final AbstractResumedStatement<?, ?, ?> existing = lookupDeclaredChild(current, childId);
+ if (existing != null) {
+ resumeStatement(existing);
+ return Optional.of(existing);
+ }
+ return Optional.empty();
}
- private void resumeStatement(final StatementContextBase<?, ?, ?> child) {
+ private void resumeStatement(final AbstractResumedStatement<?, ?, ?> child) {
if (child.isFullyDefined()) {
child.walkChildren(phase);
child.endDeclared(phase);
@Override
public void storeStatement(final int expectedChildren, final boolean fullyDefined) {
- Preconditions.checkState(current != null);
- Preconditions.checkArgument(expectedChildren >= 0);
+ checkState(current != null);
+ checkArgument(expectedChildren >= 0);
+ current.resizeSubstatements(expectedChildren);
if (fullyDefined) {
current.setFullyDefined();
}
@Override
- public void startStatement(final int childId, @Nonnull final QName name, final String argument,
- @Nonnull final StatementSourceReference ref) {
- final Optional<StatementContextBase<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
- current = existing.isPresent() ? existing.get()
- : Verify.verifyNotNull(ctx.createDeclaredChild(current, childId, name, argument, ref));
+ public void startStatement(final int childId, final QName name, final String argument,
+ final StatementSourceReference ref) {
+ final AbstractResumedStatement<?, ?, ?> existing = lookupDeclaredChild(current, childId);
+ current = existing != null ? existing
+ : verifyNotNull(ctx.createDeclaredChild(current, childId, name, argument, ref));
}
@Override
- public void endStatement(@Nonnull final StatementSourceReference ref) {
- Preconditions.checkState(current != null);
+ public void endStatement(final StatementSourceReference ref) {
+ checkState(current != null);
current.endDeclared(phase);
exitStatement();
}
- @Nonnull
@Override
public ModelProcessingPhase getPhase() {
return phase;
}
private void exitStatement() {
+ // TODO: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would:
+ // - remove the StatementSource check
+ // - allow endDeclared() to be moved to AbstractResumedStatement
+ // - remove the need for verify()
StatementContextBase<?, ?, ?> parentContext = current.getParentContext();
while (parentContext != null && StatementSource.CONTEXT == parentContext.getStatementSource()) {
parentContext.endDeclared(phase);
parentContext = parentContext.getParentContext();
}
- current = parentContext;
+ if (parentContext != null) {
+ verify(parentContext instanceof AbstractResumedStatement, "Unexpected parent context %s", parentContext);
+ current = (AbstractResumedStatement<?, ?, ?>) parentContext;
+ } else {
+ current = null;
+ }
+ }
+
+ private static @Nullable AbstractResumedStatement<?, ?, ?> lookupDeclaredChild(
+ final AbstractResumedStatement<?, ?, ?> current, final int childId) {
+ if (current == null) {
+ return null;
+ }
+
+ // Fast path: we are entering a statement which was emitted in previous phase
+ AbstractResumedStatement<?, ?, ?> existing = current.lookupSubstatement(childId);
+ while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
+ existing = existing.lookupSubstatement(childId);
+ }
+
+ return existing;
}
}