X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-reactor%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FModifierImpl.java;h=5edde2ffd80a3b391b6c6d86331cce5b11fb27a7;hb=3352bd58961fa6f5b44bfbd3415eca44a6cdd9af;hp=bf77d868050dcfb44e2a8e653dd8f447eb94eae0;hpb=5b0d78e34c4fe609824660932a5724700d11c6c4;p=yangtools.git diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java index bf77d86805..5edde2ffd8 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java @@ -7,18 +7,20 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL; import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.FULL_DECLARATION; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.base.Preconditions; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.function.Function; -import javax.annotation.Nonnull; +import org.eclipse.jdt.annotation.NonNull; 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.IdentifierNamespace; @@ -51,14 +53,14 @@ final class ModifierImpl implements ModelActionBuilder { return prereq; } - private AbstractPrerequisite addMutation(final AbstractPrerequisite mutation) { + private @NonNull AbstractPrerequisite addMutation(final @NonNull AbstractPrerequisite mutation) { LOG.trace("Modifier {} adding mutation {}", this, mutation); mutations.add(mutation); return mutation; } private void checkNotRegistered() { - Preconditions.checkState(action == null, "Action was already registered."); + checkState(action == null, "Action was already registered."); } private boolean removeSatisfied() { @@ -84,13 +86,7 @@ final class ModifierImpl implements ModelActionBuilder { action = null; } - private void applyAction() { - Preconditions.checkState(!actionApplied); - action.apply(ctx); - actionApplied = true; - } - - private , N extends StatementNamespace> AbstractPrerequisite + private , N extends StatementNamespace> @NonNull AbstractPrerequisite requiresCtxImpl(final StmtContext context, final Class namespace, final K key, final ModelProcessingPhase phase) { checkNotRegistered(); @@ -101,7 +97,7 @@ final class ModifierImpl implements ModelActionBuilder { return addedToNs; } - private , N extends StatementNamespace> AbstractPrerequisite + private , N extends StatementNamespace> @NonNull AbstractPrerequisite requiresCtxImpl(final StmtContext context, final Class namespace, final NamespaceKeyCriterion criterion, final ModelProcessingPhase phase) { checkNotRegistered(); @@ -112,7 +108,7 @@ final class ModifierImpl implements ModelActionBuilder { return addedToNs; } - private > AbstractPrerequisite requiresCtxImpl(final C context, + private > @NonNull AbstractPrerequisite requiresCtxImpl(final C context, final ModelProcessingPhase phase) { checkNotRegistered(); @@ -128,7 +124,7 @@ final class ModifierImpl implements ModelActionBuilder { final K key, final ModelProcessingPhase phase) { checkNotRegistered(); - PhaseModificationInNamespace mod = new PhaseModificationInNamespace<>(phase); + final PhaseModificationInNamespace mod = new PhaseModificationInNamespace<>(EFFECTIVE_MODEL); addReq(mod); addMutation(mod); contextImpl(context).onNamespaceItemAddedAction((Class) namespace, key, mod); @@ -136,62 +132,60 @@ final class ModifierImpl implements ModelActionBuilder { } private static StatementContextBase contextImpl(final Object value) { - Preconditions.checkArgument(value instanceof StatementContextBase, - "Supplied context %s is not provided by this reactor.", value); + checkArgument(value instanceof StatementContextBase, "Supplied context %s is not provided by this reactor.", + value); return StatementContextBase.class.cast(value); } boolean tryApply() { - Preconditions.checkState(action != null, "Action was not defined yet."); + checkState(action != null, "Action was not defined yet."); if (removeSatisfied()) { - applyAction(); + if (!actionApplied) { + action.apply(ctx); + actionApplied = true; + } return true; } return false; } - @Nonnull @Override public , T extends C> Prerequisite mutatesCtx(final T context, final ModelProcessingPhase phase) { return addMutation(new PhaseMutation<>(contextImpl(context), phase)); } - @Nonnull @Override - public ,E extends EffectiveStatement> + public , E extends EffectiveStatement> AbstractPrerequisite> requiresCtx(final StmtContext context, final ModelProcessingPhase phase) { return requiresCtxImpl(context, phase); } - @Nonnull @Override public > Prerequisite> requiresCtx( - final StmtContext context, final Class namespace, final K key, + final StmtContext context, final Class<@NonNull N> namespace, final K key, final ModelProcessingPhase phase) { return requiresCtxImpl(context, namespace, key, phase); } - @Nonnull @Override public > Prerequisite> requiresCtx( - final StmtContext context, final Class namespace, final NamespaceKeyCriterion criterion, - final ModelProcessingPhase phase) { + final StmtContext context, final Class<@NonNull N> namespace, + final NamespaceKeyCriterion criterion, final ModelProcessingPhase phase) { return requiresCtxImpl(context, namespace, criterion, phase); } - @Nonnull @Override public > Prerequisite requiresDeclared( final StmtContext context) { return requiresCtxImpl(context, FULL_DECLARATION).transform(StmtContext::buildDeclared); } - @Nonnull @Override + @Deprecated public , N extends StatementNamespace> Prerequisite requiresDeclared(final StmtContext context, final Class namespace, final K key) { final AbstractPrerequisite> rawContext = requiresCtxImpl(context, namespace, key, @@ -199,23 +193,23 @@ final class ModifierImpl implements ModelActionBuilder { return rawContext.transform(StmtContext::buildDeclared); } - @Nonnull @Override + @Deprecated public , N extends StatementNamespace> AbstractPrerequisite> requiresDeclaredCtx(final StmtContext context, final Class namespace, final K key) { return requiresCtxImpl(context, namespace, key, FULL_DECLARATION); } - @Nonnull @Override + @Deprecated public > Prerequisite requiresEffective( final StmtContext stmt) { return requiresCtxImpl(stmt, EFFECTIVE_MODEL).transform(StmtContext::buildEffective); } - @Nonnull @Override + @Deprecated public , N extends StatementNamespace> Prerequisite requiresEffective(final StmtContext context, final Class namespace, final K key) { final AbstractPrerequisite> rawContext = requiresCtxImpl(context, namespace, key, @@ -223,22 +217,21 @@ final class ModifierImpl implements ModelActionBuilder { return rawContext.transform(StmtContext::buildEffective); } - @Nonnull @Override + @Deprecated public , N extends StatementNamespace> AbstractPrerequisite> requiresEffectiveCtx(final StmtContext context, final Class namespace, final K key) { return requiresCtxImpl(contextImpl(context), namespace, key, EFFECTIVE_MODEL); } - @Nonnull @Override + @Deprecated public > Prerequisite> mutatesNs( final Mutable context, final Class namespace) { return addMutation(new NamespaceMutation<>(contextImpl(context), namespace)); } - @Nonnull @Override public , N extends IdentifierNamespace>> AbstractPrerequisite> mutatesEffectiveCtx(final StmtContext context, @@ -246,11 +239,26 @@ final class ModifierImpl implements ModelActionBuilder { return mutatesCtxImpl(context, namespace, key, EFFECTIVE_MODEL); } + @Override + public , N extends IdentifierNamespace>> + AbstractPrerequisite> mutatesEffectiveCtxPath(final StmtContext context, + final Class namespace, final Iterable keys) { + checkNotRegistered(); + + final PhaseModificationInNamespacePath, K, N> ret = new PhaseModificationInNamespacePath<>( + EFFECTIVE_MODEL, keys); + addReq(ret); + addMutation(ret); + + ret.hookOnto(context, namespace); + return ret; + } + @Override @SuppressWarnings("checkstyle:hiddenField") public void apply(final InferenceAction action) { - Preconditions.checkState(this.action == null, "Action already defined to %s", this.action); - this.action = Preconditions.checkNotNull(action); + checkState(this.action == null, "Action already defined to %s", this.action); + this.action = requireNonNull(action); } private abstract class AbstractPrerequisite implements Prerequisite { @@ -260,9 +268,9 @@ final class ModifierImpl implements ModelActionBuilder { @Override @SuppressWarnings("checkstyle:hiddenField") public final T resolve(final InferenceContext ctx) { - Preconditions.checkState(done); - Preconditions.checkArgument(ctx == ModifierImpl.this.ctx); - return value; + checkState(done); + checkArgument(ctx == ModifierImpl.this.ctx); + return verifyNotNull(value, "Attempted to access unavailable prerequisite %s", this); } final boolean isDone() { @@ -276,7 +284,7 @@ final class ModifierImpl implements ModelActionBuilder { return isApplied(); } - final Prerequisite transform(final Function transformation) { + final @NonNull Prerequisite transform(final Function transformation) { return context -> transformation.apply(resolve(context)); } @@ -290,7 +298,7 @@ final class ModifierImpl implements ModelActionBuilder { } } - private class PhaseMutation extends AbstractPrerequisite implements ContextMutation { + private final class PhaseMutation extends AbstractPrerequisite implements ContextMutation { @SuppressWarnings("unchecked") PhaseMutation(final StatementContextBase context, final ModelProcessingPhase phase) { context.addMutation(phase, this); @@ -303,24 +311,24 @@ final class ModifierImpl implements ModelActionBuilder { } } - private class PhaseFinished> extends AbstractPrerequisite + private final class PhaseFinished> extends AbstractPrerequisite implements OnPhaseFinished { @SuppressWarnings("unchecked") @Override public boolean phaseFinished(final StatementContextBase context, final ModelProcessingPhase finishedPhase) { - return resolvePrereq((C) context); + return resolvePrereq((C) context) || tryApply(); } } - private class NamespaceMutation> + private final class NamespaceMutation> extends AbstractPrerequisite> { NamespaceMutation(final StatementContextBase ctx, final Class namespace) { resolvePrereq(ctx); } } - private class AddedToNamespace> extends AbstractPrerequisite + private final class AddedToNamespace> extends AbstractPrerequisite implements OnNamespaceItemAdded, OnPhaseFinished { private final ModelProcessingPhase phase; @@ -338,7 +346,7 @@ final class ModifierImpl implements ModelActionBuilder { @Override public boolean phaseFinished(final StatementContextBase context, final ModelProcessingPhase finishedPhase) { - return resolvePrereq((C) context); + return resolvePrereq((C) context) || tryApply(); } @Override @@ -347,12 +355,12 @@ final class ModifierImpl implements ModelActionBuilder { } } - private class PhaseModificationInNamespace> extends AbstractPrerequisite + private final class PhaseModificationInNamespace> extends AbstractPrerequisite implements OnNamespaceItemAdded, ContextMutation { private final ModelProcessingPhase modPhase; PhaseModificationInNamespace(final ModelProcessingPhase phase) { - Preconditions.checkArgument(phase != null, "Model processing phase must not be null"); + checkArgument(phase != null, "Model processing phase must not be null"); this.modPhase = phase; } @@ -370,4 +378,74 @@ final class ModifierImpl implements ModelActionBuilder { return isApplied(); } } + + /** + * This similar to {@link PhaseModificationInNamespace}, but allows recursive descent until it finds the real + * target. The mechanics is driven as a sequence of prerequisites along a path: first we hook onto namespace to + * give us the first step. When it does, we hook onto the first item to provide us the second step and so on. + */ + private final class PhaseModificationInNamespacePath, K, + N extends IdentifierNamespace>> extends AbstractPrerequisite + implements OnNamespaceItemAdded, ContextMutation { + private final ModelProcessingPhase modPhase; + private final Iterable keys; + private final Iterator it; + + PhaseModificationInNamespacePath(final ModelProcessingPhase phase, final Iterable keys) { + this.modPhase = requireNonNull(phase); + this.keys = requireNonNull(keys); + it = keys.iterator(); + } + + @Override + public boolean isFinished() { + return isApplied(); + } + + @Override + public void namespaceItemAdded(final StatementContextBase context, final Class namespace, + final Object key, final Object value) { + LOG.debug("Action for {} got key {}", keys, key); + + final StatementContextBase target = contextImpl(value); + if (!target.isSupportedByFeatures()) { + LOG.debug("Key {} in {} is not supported", key, keys); + resolvePrereq(null); + action.prerequisiteUnavailable(this); + return; + } + + // Hook onto target: we either have a modification of the target itself or one of its children. + target.addMutation(modPhase, this); + // We have completed the context -> target step, hence we are no longer directly blocking context from + // making forward progress. + context.removeMutation(modPhase, this); + + if (!it.hasNext()) { + // Last step: we are done + if (resolvePrereq((C) value)) { + tryApply(); + } + return; + } + + // Make sure target's storage notifies us when the next step becomes available. + hookOnto(target, namespace, it.next()); + } + + @Override + ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { + return super.addToStringAttributes(toStringHelper).add("phase", modPhase).add("keys", keys); + } + + void hookOnto(final StmtContext context, final Class namespace) { + checkArgument(it.hasNext(), "Namespace %s keys may not be empty", namespace); + hookOnto(contextImpl(context), namespace, it.next()); + } + + @SuppressWarnings("unchecked") + private void hookOnto(final StatementContextBase context, final Class namespace, final K key) { + context.onNamespaceItemAddedAction((Class) namespace, requireNonNull(key), this); + } + } }