X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=inline;f=yang%2Fyang-parser-reactor%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FStatementContextBase.java;h=109ffbc5370859e9b524cede4bc9735b65a0f1e6;hb=27ce190366ae9efbce8c3a4b21c81cb20b10b8e3;hp=fc83c28ed34a989744d3357356fc9f4dc0f73439;hpb=485db12bb79d299e44957dc66d96f23e1239c857;p=yangtools.git diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index fc83c28ed3..109ffbc537 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -8,12 +8,13 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; 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.annotations.Beta; +import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; @@ -30,7 +31,6 @@ import java.util.Map.Entry; 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.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; @@ -40,6 +40,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; import org.opendaylight.yangtools.yang.parser.spi.meta.ImplicitParentAwareStatementSupport; 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.MutableStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion; @@ -64,7 +65,7 @@ import org.slf4j.LoggerFactory; * @param Effective Statement representation */ public abstract class StatementContextBase, E extends EffectiveStatement> - extends ReactorStmtCtx { + extends ReactorStmtCtx implements CopyHistory { /** * Event listener when an item is added to model namespace. */ @@ -95,34 +96,82 @@ public abstract class StatementContextBase, E private static final Logger LOG = LoggerFactory.getLogger(StatementContextBase.class); - private final CopyHistory copyHistory; + // + // {@link CopyHistory} encoded as a single byte. We still have 4 bits unused. + // + private static final byte COPY_LAST_TYPE_MASK = 0x03; + private static final byte COPY_ADDED_BY_USES = 0x04; + private static final byte COPY_ADDED_BY_AUGMENTATION = 0x08; + private static final byte COPY_ORIGINAL = 0x00; + + private final byte copyHistory; + + static { + final int copyTypes = CopyType.values().length; + // This implies CopyType.ordinal() is <= COPY_TYPE_MASK + verify(copyTypes == COPY_LAST_TYPE_MASK + 1, "Unexpected %s CopyType values", copyTypes); + } + // Note: this field can strictly be derived in InferredStatementContext, but it forms the basis of many of our // operations, hence we want to keep it close by. private final @NonNull StatementDefinitionContext definition; + // TODO: consider keying by Byte equivalent of ExecutionOrder private Multimap phaseListeners = ImmutableMultimap.of(); private Multimap phaseMutation = ImmutableMultimap.of(); private List> effectOfStatement = ImmutableList.of(); - private @Nullable ModelProcessingPhase completedPhase; + /** + * {@link ModelProcessingPhase.ExecutionOrder} value of current {@link ModelProcessingPhase} of this statement. + */ + private byte executionOrder; // Copy constructor used by subclasses to implement reparent() StatementContextBase(final StatementContextBase original) { super(original); this.copyHistory = original.copyHistory; this.definition = original.definition; - this.completedPhase = original.completedPhase; + this.executionOrder = original.executionOrder; } StatementContextBase(final StatementDefinitionContext def) { this.definition = requireNonNull(def); - this.copyHistory = CopyHistory.original(); + this.copyHistory = COPY_ORIGINAL; + } + + StatementContextBase(final StatementDefinitionContext def, final byte copyHistory) { + this.definition = requireNonNull(def); + this.copyHistory = copyHistory; } - StatementContextBase(final StatementDefinitionContext def, final CopyHistory copyHistory) { + StatementContextBase(final StatementDefinitionContext def, final CopyType copyType) { this.definition = requireNonNull(def); - this.copyHistory = requireNonNull(copyHistory); + this.copyHistory = (byte) copyFlags(copyType); + } + + StatementContextBase(final StatementContextBase prototype, final CopyType copyType) { + this.definition = prototype.definition; + this.copyHistory = (byte) (copyFlags(copyType) | prototype.copyHistory & ~COPY_LAST_TYPE_MASK); + } + + private static int copyFlags(final CopyType copyType) { + return historyFlags(copyType) | copyType.ordinal(); + } + + private static byte historyFlags(final CopyType copyType) { + switch (copyType) { + case ADDED_BY_AUGMENTATION: + return COPY_ADDED_BY_AUGMENTATION; + case ADDED_BY_USES: + return COPY_ADDED_BY_USES; + case ADDED_BY_USES_AUGMENTATION: + return COPY_ADDED_BY_AUGMENTATION | COPY_ADDED_BY_USES; + case ORIGINAL: + return COPY_ORIGINAL; + default: + throw new VerifyException("Unhandled type " + copyType); + } } @Override @@ -142,20 +191,43 @@ public abstract class StatementContextBase, E effectOfStatement.addAll(ctxs); } + // + // CopyHistory integration + // + @Override public final CopyHistory history() { - return copyHistory; + return this; } @Override - public final ModelProcessingPhase getCompletedPhase() { - return completedPhase; + public final boolean isAddedByUses() { + return (copyHistory & COPY_ADDED_BY_USES) != 0; + } + + @Override + public final boolean isAugmenting() { + return (copyHistory & COPY_ADDED_BY_AUGMENTATION) != 0; + } + + @Override + public final CopyType getLastOperation() { + return CopyType.values()[copyHistory & COPY_LAST_TYPE_MASK]; + } + + // + // Inference completion tracking + // + + @Override + final byte executionOrder() { + return executionOrder; } // FIXME: this should be propagated through a correct constructor @Deprecated final void setCompletedPhase(final ModelProcessingPhase completedPhase) { - this.completedPhase = completedPhase; + this.executionOrder = completedPhase.executionOrder(); } @Override @@ -257,10 +329,7 @@ public abstract class StatementContextBase, E final List> resized = beforeAddEffectiveStatement(effective, 1); final ReactorStmtCtx stmt = (ReactorStmtCtx) substatement; - final ModelProcessingPhase phase = completedPhase; - if (phase != null) { - ensureCompletedPhase(stmt, phase); - } + ensureCompletedExecution(stmt); resized.add(stmt); return resized; } @@ -288,10 +357,9 @@ public abstract class StatementContextBase, E final List> resized = beforeAddEffectiveStatement(effective, statements.size()); final Collection> casted = (Collection>) statements; - final ModelProcessingPhase phase = completedPhase; - if (phase != null) { + if (executionOrder != ExecutionOrder.NULL) { for (ReactorStmtCtx stmt : casted) { - ensureCompletedPhase(stmt, phase); + ensureCompletedExecution(stmt, executionOrder); } } @@ -304,17 +372,20 @@ public abstract class StatementContextBase, E // exposed for InferredStatementContext only final void ensureCompletedPhase(final Mutable stmt) { verifyStatement(stmt); - final ModelProcessingPhase phase = completedPhase; - if (phase != null) { - ensureCompletedPhase((ReactorStmtCtx) stmt, phase); + ensureCompletedExecution((ReactorStmtCtx) stmt); + } + + // Make sure target statement has transitioned at least to our phase (if we have one). This method is just before we + // take allow a statement to become our substatement. This is needed to ensure that every statement tree does not + // contain any statements which did not complete the same phase as the root statement. + private void ensureCompletedExecution(final ReactorStmtCtx stmt) { + if (executionOrder != ExecutionOrder.NULL) { + ensureCompletedExecution(stmt, executionOrder); } } - // Make sure target statement has transitioned at least to specified phase. This method is just before we take - // allow a statement to become our substatement. This is needed to ensure that every statement tree does not contain - // any statements which did not complete the same phase as the root statement. - private static void ensureCompletedPhase(final ReactorStmtCtx stmt, final ModelProcessingPhase phase) { - verify(stmt.tryToCompletePhase(phase), "Statement %s cannot complete phase %s", stmt, phase); + private static void ensureCompletedExecution(final ReactorStmtCtx stmt, final byte executionOrder) { + verify(stmt.tryToCompletePhase(executionOrder), "Statement %s cannot complete phase %s", stmt, executionOrder); } private static void verifyStatement(final Mutable stmt) { @@ -323,8 +394,10 @@ public abstract class StatementContextBase, E private List> beforeAddEffectiveStatement(final List> effective, final int toAdd) { - // We cannot allow statement to be further mutated - verify(completedPhase != ModelProcessingPhase.EFFECTIVE_MODEL, "Cannot modify finished statement at %s", + // We cannot allow statement to be further mutated. + // TODO: we really want to say 'not NULL and not at or after EFFECTIVE_MODEL here. This will matter if we have + // a phase after EFFECTIVE_MODEL + verify(executionOrder != ExecutionOrder.EFFECTIVE_MODEL, "Cannot modify finished statement at %s", sourceReference()); return beforeAddEffectiveStatementUnsafe(effective, toAdd); } @@ -377,27 +450,28 @@ public abstract class StatementContextBase, E abstract Stream> streamEffective(); @Override - final boolean doTryToCompletePhase(final ModelProcessingPhase phase) { - final boolean finished = phaseMutation.isEmpty() ? true : runMutations(phase); - if (completeChildren(phase) && finished) { - onPhaseCompleted(phase); + final boolean doTryToCompletePhase(final byte targetOrder) { + final boolean finished = phaseMutation.isEmpty() ? true : runMutations(targetOrder); + if (completeChildren(targetOrder) && finished) { + onPhaseCompleted(targetOrder); return true; } return false; } - private boolean completeChildren(final ModelProcessingPhase phase) { + private boolean completeChildren(final byte targetOrder) { boolean finished = true; for (final StatementContextBase child : mutableDeclaredSubstatements()) { - finished &= child.tryToCompletePhase(phase); + finished &= child.tryToCompletePhase(targetOrder); } for (final ReactorStmtCtx child : effectiveChildrenToComplete()) { - finished &= child.tryToCompletePhase(phase); + finished &= child.tryToCompletePhase(targetOrder); } return finished; } - private boolean runMutations(final ModelProcessingPhase phase) { + private boolean runMutations(final byte targetOrder) { + final ModelProcessingPhase phase = verifyNotNull(ModelProcessingPhase.ofExecutionOrder(targetOrder)); final Collection openMutations = phaseMutation.get(phase); return openMutations.isEmpty() ? true : runMutations(phase, openMutations); } @@ -428,19 +502,20 @@ public abstract class StatementContextBase, E } /** - * Occurs on end of {@link ModelProcessingPhase} of source parsing. + * Occurs on end of {@link ModelProcessingPhase} of source parsing. This method must not be called with + * {@code executionOrder} equal to {@link ExecutionOrder#NULL}. * - * @param phase - * that was to be completed (finished) - * @throws SourceException - * when an error occurred in source parsing + * @param phase that was to be completed (finished) + * @throws SourceException when an error occurred in source parsing */ - private void onPhaseCompleted(final ModelProcessingPhase phase) { - completedPhase = phase; - if (phase == ModelProcessingPhase.EFFECTIVE_MODEL) { + private void onPhaseCompleted(final byte completedOrder) { + executionOrder = completedOrder; + if (completedOrder == ExecutionOrder.EFFECTIVE_MODEL) { + // We have completed effective model, substatements are guaranteed not to change summarizeSubstatementPolicy(); } + final ModelProcessingPhase phase = verifyNotNull(ModelProcessingPhase.ofExecutionOrder(completedOrder)); final Collection listeners = phaseListeners.get(phase); if (!listeners.isEmpty()) { runPhaseListeners(phase, listeners); @@ -607,10 +682,10 @@ public abstract class StatementContextBase, E * @throws NullPointerException if any of the arguments is null */ void addPhaseCompletedListener(final ModelProcessingPhase phase, final OnPhaseFinished listener) { - checkNotNull(phase, "Statement context processing phase cannot be null at: %s", sourceReference()); - checkNotNull(listener, "Statement context phase listener cannot be null at: %s", sourceReference()); + requireNonNull(phase, "Statement context processing phase cannot be null"); + requireNonNull(listener, "Statement context phase listener cannot be null"); - ModelProcessingPhase finishedPhase = completedPhase; + ModelProcessingPhase finishedPhase = ModelProcessingPhase.ofExecutionOrder(executionOrder); while (finishedPhase != null) { if (phase.equals(finishedPhase)) { listener.phaseFinished(this, finishedPhase); @@ -631,12 +706,8 @@ public abstract class StatementContextBase, E * @throws IllegalStateException when the mutation was registered after phase was completed */ final void addMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { - ModelProcessingPhase finishedPhase = completedPhase; - while (finishedPhase != null) { - checkState(!phase.equals(finishedPhase), "Mutation registered after phase was completed at: %s", - sourceReference()); - finishedPhase = finishedPhase.getPreviousPhase(); - } + checkState(executionOrder < phase.executionOrder(), "Mutation registered after phase was completed at: %s", + sourceReference()); if (phaseMutation.isEmpty()) { phaseMutation = newMultimap();