final ModelProcessingPhase phase) {
checkNotRegistered();
- AddedToNamespace<C> addedToNs = new AddedToNamespace<>(phase);
+ final var addedToNs = new AddedToNamespace<C>(this, phase);
addReq(addedToNs);
contextImpl(context).onNamespaceItemAddedAction(namespace, key, addedToNs);
return addedToNs;
final NamespaceKeyCriterion<K> criterion, final ModelProcessingPhase phase) {
checkNotRegistered();
- AddedToNamespace<C> addedToNs = new AddedToNamespace<>(phase);
+ final var addedToNs = new AddedToNamespace<C>(this, phase);
addReq(addedToNs);
contextImpl(context).onNamespaceItemAddedAction(namespace, phase, criterion, addedToNs);
return addedToNs;
final ModelProcessingPhase phase) {
checkNotRegistered();
- PhaseFinished<C> phaseFin = new PhaseFinished<>();
+ final var phaseFin = new PhaseFinished<C>(this);
addReq(phaseFin);
- contextImpl(context).addPhaseCompletedListener(phase, phaseFin);
+ addBootstrap(() -> contextImpl(context).addPhaseCompletedListener(phase, phaseFin));
return phaseFin;
}
final K key, final ModelProcessingPhase phase) {
checkNotRegistered();
- final PhaseModificationInNamespace<C> mod = new PhaseModificationInNamespace<>(EFFECTIVE_MODEL);
+ final var mod = new PhaseModificationInNamespace<C>(this, EFFECTIVE_MODEL);
addReq(mod);
addMutation(mod);
contextImpl(context).onNamespaceItemAddedAction((Class) namespace, key, mod);
@Override
public <C extends Mutable<?, ?, ?>, T extends C> Prerequisite<C> mutatesCtx(final T context,
final ModelProcessingPhase phase) {
- return addMutation(new PhaseMutation<>(contextImpl(context), phase));
+ return addMutation(new PhaseMutation<>(this, contextImpl(context), phase));
}
@Override
return requiresCtxImpl(context, phase);
}
-
@Override
public <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
final StmtContext<?, ?, ?> context, final Class<@NonNull N> namespace, final K key,
return requiresCtxImpl(context, namespace, criterion, phase);
}
+ @Override
+ public <K, E extends EffectiveStatement<?, ?>, N extends ParserNamespace<K, ? extends StmtContext<?, ?, ?>>>
+ Prerequisite<StmtContext<?, ?, E>> requiresCtxPath(final StmtContext<?, ?, ?> context,
+ final Class<N> namespace, final Iterable<K> keys, final ModelProcessingPhase phase) {
+ checkNotRegistered();
+
+ final var ret = new PhaseRequirementInNamespacePath<StmtContext<?, ?, E>, K, N>(this, EFFECTIVE_MODEL, keys);
+ addReq(ret);
+ addBootstrap(() -> ret.hookOnto(context, namespace));
+ return ret;
+ }
+
@Override
public <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(
final StmtContext<?, ? extends D, ?> context) {
@Deprecated
public <N extends ParserNamespace<?, ?>> Prerequisite<Mutable<?, ?, ?>> mutatesNs(final Mutable<?, ?, ?> context,
final Class<N> namespace) {
- return addMutation(new NamespaceMutation<>(contextImpl(context), namespace));
+ return addMutation(new NamespaceMutation<>(this, contextImpl(context), namespace));
}
@Override
final Class<N> namespace, final Iterable<K> keys) {
checkNotRegistered();
- final PhaseModificationInNamespacePath<Mutable<?, ?, E>, K, N> ret = new PhaseModificationInNamespacePath<>(
- EFFECTIVE_MODEL, keys);
+ final var ret = new PhaseModificationInNamespacePath<Mutable<?, ?, E>, K, N>(this, EFFECTIVE_MODEL, keys);
addReq(ret);
addMutation(ret);
-
- if (bootstraps == null) {
- bootstraps = new ArrayList<>(1);
- }
- bootstraps.add(() -> ret.hookOnto(context, namespace));
+ addBootstrap(() -> ret.hookOnto(context, namespace));
return ret;
}
}
}
- private abstract class AbstractPrerequisite<T> implements Prerequisite<T> {
+ private void addBootstrap(final Runnable bootstrap) {
+ if (bootstraps == null) {
+ bootstraps = new ArrayList<>(1);
+ }
+ bootstraps.add(bootstrap);
+ }
+
+ private abstract static class AbstractPrerequisite<T> implements Prerequisite<T> {
+ final @NonNull ModifierImpl modifier;
+
private boolean done = false;
private T value;
+ AbstractPrerequisite(final ModifierImpl modifier) {
+ this.modifier = requireNonNull(modifier);
+ }
+
@Override
@SuppressWarnings("checkstyle:hiddenField")
public final T resolve(final InferenceContext ctx) {
checkState(done);
- checkArgument(ctx == ModifierImpl.this.ctx);
+ checkArgument(ctx == modifier.ctx);
return verifyNotNull(value, "Attempted to access unavailable prerequisite %s", this);
}
final boolean resolvePrereq(final T value) {
this.value = value;
this.done = true;
- return isApplied();
+ return modifier.isApplied();
}
final <O> @NonNull Prerequisite<O> transform(final Function<? super T, O> transformation) {
}
}
- private final class PhaseMutation<C> extends AbstractPrerequisite<C> implements ContextMutation {
+ private abstract static class AbstractPathPrerequisite<C extends StmtContext<?, ?, ?>, K,
+ N extends ParserNamespace<K, ? extends StmtContext<?, ?, ?>>> extends AbstractPrerequisite<C>
+ implements OnNamespaceItemAdded {
+ private final ModelProcessingPhase modPhase;
+ private final Iterable<K> keys;
+ private final Iterator<K> it;
+
+ AbstractPathPrerequisite(final ModifierImpl modifier, final ModelProcessingPhase phase,
+ final Iterable<K> keys) {
+ super(modifier);
+ this.modPhase = requireNonNull(phase);
+ this.keys = requireNonNull(keys);
+ it = keys.iterator();
+ }
+
+ @Override
+ public final 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);
+ modifier.action.prerequisiteUnavailable(this);
+ return;
+ }
+
+ nextStep(modPhase, context, target);
+
+ if (!it.hasNext()) {
+ // Last step: we are done
+ if (resolvePrereq((C) value)) {
+ modifier.tryApply();
+ }
+ return;
+ }
+
+ // Make sure target's storage notifies us when the next step becomes available.
+ hookOnto(target, namespace, it.next());
+ }
+
+ abstract void nextStep(ModelProcessingPhase phase, StatementContextBase<?, ?, ?> current,
+ StatementContextBase<?, ?, ?> next);
+
+ @Override
+ final ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("phase", modPhase).add("keys", keys);
+ }
+
+ final 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);
+ }
+ }
+
+ private static final class PhaseMutation<C> extends AbstractPrerequisite<C> implements ContextMutation {
@SuppressWarnings("unchecked")
- PhaseMutation(final StatementContextBase<?, ?, ?> context, final ModelProcessingPhase phase) {
+ PhaseMutation(final ModifierImpl modifier, final StatementContextBase<?, ?, ?> context,
+ final ModelProcessingPhase phase) {
+ super(modifier);
context.addMutation(phase, this);
resolvePrereq((C) context);
}
@Override
public boolean isFinished() {
- return isApplied();
+ return modifier.isApplied();
}
}
- private final class PhaseFinished<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C>
+ private static final class PhaseFinished<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C>
implements OnPhaseFinished {
+ PhaseFinished(final ModifierImpl modifier) {
+ super(modifier);
+ }
+
@SuppressWarnings("unchecked")
@Override
public boolean phaseFinished(final StatementContextBase<?, ?, ?> context,
final ModelProcessingPhase finishedPhase) {
- return resolvePrereq((C) context) || tryApply();
+ return resolvePrereq((C) context) || modifier.tryApply();
}
}
- private final class NamespaceMutation<N extends ParserNamespace<?, ?>>
+ private static final class NamespaceMutation<N extends ParserNamespace<?, ?>>
extends AbstractPrerequisite<Mutable<?, ?, ?>> {
- NamespaceMutation(final StatementContextBase<?, ?, ?> ctx, final Class<N> namespace) {
+ NamespaceMutation(final ModifierImpl modifier, final StatementContextBase<?, ?, ?> ctx,
+ final Class<N> namespace) {
+ super(modifier);
resolvePrereq(ctx);
}
}
- private final class AddedToNamespace<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C>
+ private static final class AddedToNamespace<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C>
implements OnNamespaceItemAdded, OnPhaseFinished {
private final ModelProcessingPhase phase;
- AddedToNamespace(final ModelProcessingPhase phase) {
+ AddedToNamespace(final ModifierImpl modifier, final ModelProcessingPhase phase) {
+ super(modifier);
this.phase = requireNonNull(phase);
}
@Override
public void namespaceItemAdded(final StatementContextBase<?, ?, ?> context, final Class<?> namespace,
final Object key, final Object value) {
- ((StatementContextBase<?, ?, ?>) value).addPhaseCompletedListener(phase, this);
+ contextImpl(value).addPhaseCompletedListener(phase, this);
}
@SuppressWarnings("unchecked")
@Override
public boolean phaseFinished(final StatementContextBase<?, ?, ?> context,
final ModelProcessingPhase finishedPhase) {
- return resolvePrereq((C) context) || tryApply();
+ return resolvePrereq((C) context) || modifier.tryApply();
}
@Override
}
}
- private final class PhaseModificationInNamespace<C extends Mutable<?, ?, ?>> extends AbstractPrerequisite<C>
+ private static final class PhaseRequirementInNamespacePath<C extends StmtContext<?, ?, ?>, K,
+ N extends ParserNamespace<K, ? extends StmtContext<?, ?, ?>>> extends AbstractPathPrerequisite<C, K, N> {
+ PhaseRequirementInNamespacePath(final ModifierImpl modifier, final ModelProcessingPhase phase,
+ final Iterable<K> keys) {
+ super(modifier, phase, keys);
+ }
+
+ @Override
+ void nextStep(final ModelProcessingPhase phase, final StatementContextBase<?, ?, ?> current,
+ final StatementContextBase<?, ?, ?> next) {
+ // No-op
+ }
+ }
+
+ private static final class PhaseModificationInNamespace<C extends Mutable<?, ?, ?>> extends AbstractPrerequisite<C>
implements OnNamespaceItemAdded, ContextMutation {
private final ModelProcessingPhase modPhase;
- PhaseModificationInNamespace(final ModelProcessingPhase phase) {
+ PhaseModificationInNamespace(final ModifierImpl modifier, final ModelProcessingPhase phase) {
+ super(modifier);
checkArgument(phase != null, "Model processing phase must not be null");
this.modPhase = phase;
}
@Override
public boolean isFinished() {
- return isApplied();
+ return modifier.isApplied();
}
}
* 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<C extends Mutable<?, ?, ?>, K,
- N extends ParserNamespace<K, ? extends StmtContext<?, ?, ?>>> extends AbstractPrerequisite<C>
- implements OnNamespaceItemAdded, ContextMutation {
- private final ModelProcessingPhase modPhase;
- private final Iterable<K> keys;
- private final Iterator<K> it;
-
- PhaseModificationInNamespacePath(final ModelProcessingPhase phase, final Iterable<K> keys) {
- this.modPhase = requireNonNull(phase);
- this.keys = requireNonNull(keys);
- it = keys.iterator();
+ private static final class PhaseModificationInNamespacePath<C extends Mutable<?, ?, ?>, K,
+ N extends ParserNamespace<K, ? extends StmtContext<?, ?, ?>>> extends AbstractPathPrerequisite<C, K, N>
+ implements ContextMutation {
+ PhaseModificationInNamespacePath(final ModifierImpl modifier, final ModelProcessingPhase phase,
+ final Iterable<K> keys) {
+ super(modifier, phase, keys);
}
@Override
public boolean isFinished() {
- return isApplied();
+ return modifier.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;
- }
-
+ void nextStep(final ModelProcessingPhase phase, final StatementContextBase<?, ?, ?> current,
+ final StatementContextBase<?, ?, ?> next) {
// Hook onto target: we either have a modification of the target itself or one of its children.
- target.addMutation(modPhase, this);
+ next.addMutation(phase, 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);
+ current.removeMutation(phase, this);
}
}
}