2 * Copyright (c) 2015, 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL;
12 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.FULL_DECLARATION;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.base.MoreObjects.ToStringHelper;
16 import com.google.common.base.Preconditions;
17 import java.util.HashSet;
18 import java.util.Iterator;
20 import java.util.function.Function;
21 import javax.annotation.Nonnull;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
30 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextMutation;
31 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnNamespaceItemAdded;
32 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnPhaseFinished;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 final class ModifierImpl implements ModelActionBuilder {
37 private static final Logger LOG = LoggerFactory.getLogger(ModifierImpl.class);
39 private final InferenceContext ctx = new InferenceContext() { };
41 private final Set<AbstractPrerequisite<?>> unsatisfied = new HashSet<>(1);
42 private final Set<AbstractPrerequisite<?>> mutations = new HashSet<>(1);
44 private InferenceAction action;
45 private boolean actionApplied = false;
47 private <D> AbstractPrerequisite<D> addReq(final AbstractPrerequisite<D> prereq) {
48 LOG.trace("Modifier {} adding prerequisite {}", this, prereq);
49 unsatisfied.add(prereq);
53 private <T> AbstractPrerequisite<T> addMutation(final AbstractPrerequisite<T> mutation) {
54 LOG.trace("Modifier {} adding mutation {}", this, mutation);
55 mutations.add(mutation);
59 private void checkNotRegistered() {
60 Preconditions.checkState(action == null, "Action was already registered.");
63 private boolean removeSatisfied() {
64 final Iterator<AbstractPrerequisite<?>> it = unsatisfied.iterator();
65 while (it.hasNext()) {
66 final AbstractPrerequisite<?> prereq = it.next();
67 if (prereq.isDone()) {
68 // We are removing current prerequisite from list.
69 LOG.trace("Modifier {} prerequisite {} satisfied", this, prereq);
73 return unsatisfied.isEmpty();
82 action.prerequisiteFailed(unsatisfied);
86 private void applyAction() {
87 Preconditions.checkState(!actionApplied);
92 @SuppressWarnings({ "unchecked", "rawtypes" })
93 private <K, C extends StmtContext<?,?,?>, N extends StatementNamespace<K, ?, ?>> AbstractPrerequisite<C>
94 requiresCtxImpl(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key,
95 final ModelProcessingPhase phase) {
98 AddedToNamespace<C> addedToNs = new AddedToNamespace<>(phase);
100 contextImpl(context).onNamespaceItemAddedAction((Class) namespace, key, addedToNs);
104 private <C extends StmtContext<?, ?, ?>> AbstractPrerequisite<C> requiresCtxImpl(final C context,
105 final ModelProcessingPhase phase) {
106 checkNotRegistered();
108 PhaseFinished<C> phaseFin = new PhaseFinished<>();
110 contextImpl(context).addPhaseCompletedListener(phase, phaseFin);
114 @SuppressWarnings({ "rawtypes", "unchecked" })
115 private <K, C extends StmtContext.Mutable<?, ?, ?>,
116 N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> AbstractPrerequisite<C> mutatesCtxImpl(
117 final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key,
118 final ModelProcessingPhase phase) {
119 checkNotRegistered();
121 PhaseModificationInNamespace<C> mod = new PhaseModificationInNamespace<>(phase);
124 contextImpl(context).onNamespaceItemAddedAction((Class) namespace, key, mod);
128 private static StatementContextBase<?,?,?> contextImpl(final Object value) {
129 Preconditions.checkArgument(value instanceof StatementContextBase,
130 "Supplied context %s is not provided by this reactor.", value);
131 return StatementContextBase.class.cast(value);
135 Preconditions.checkState(action != null, "Action was not defined yet.");
137 if (removeSatisfied()) {
146 public <C extends Mutable<?, ?, ?>, CT extends C> Prerequisite<C> mutatesCtx(final CT context,
147 final ModelProcessingPhase phase) {
148 return addMutation(new PhaseMutation<>(contextImpl(context), phase));
153 public <A,D extends DeclaredStatement<A>,E extends EffectiveStatement<A, D>>
154 AbstractPrerequisite<StmtContext<A, D, E>> requiresCtx(final StmtContext<A, D, E> context,
155 final ModelProcessingPhase phase) {
156 return requiresCtxImpl(context, phase);
162 public <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
163 final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key,
164 final ModelProcessingPhase phase) {
165 return requiresCtxImpl(context, namespace, key, phase);
170 public <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(
171 final StmtContext<?, ? extends D, ?> context) {
172 return requiresCtxImpl(context, FULL_DECLARATION).transform(StmtContext::buildDeclared);
177 public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> Prerequisite<D>
178 requiresDeclared(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key) {
179 final AbstractPrerequisite<StmtContext<?, D, ?>> rawContext = requiresCtxImpl(context, namespace, key,
181 return rawContext.transform(StmtContext::buildDeclared);
186 public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
187 AbstractPrerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(final StmtContext<?, ?, ?> context,
188 final Class<N> namespace, final K key) {
189 return requiresCtxImpl(context, namespace, key, FULL_DECLARATION);
194 public <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(
195 final StmtContext<?, ?, ? extends E> stmt) {
196 return requiresCtxImpl(stmt, EFFECTIVE_MODEL).transform(StmtContext::buildEffective);
201 public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> Prerequisite<E>
202 requiresEffective(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key) {
203 final AbstractPrerequisite<StmtContext<?,?,E>> rawContext = requiresCtxImpl(context, namespace, key,
205 return rawContext.transform(StmtContext::buildEffective);
210 public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
211 AbstractPrerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(final StmtContext<?, ?, ?> context,
212 final Class<N> namespace, final K key) {
213 return requiresCtxImpl(contextImpl(context), namespace, key, EFFECTIVE_MODEL);
218 public <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?, ?, ?>> mutatesNs(
219 final Mutable<?, ?, ?> context, final Class<N> namespace) {
220 return addMutation(new NamespaceMutation<>(contextImpl(context), namespace));
225 public <K, E extends EffectiveStatement<?, ?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>>
226 AbstractPrerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(final StmtContext<?, ?, ?> context,
227 final Class<N> namespace, final K key) {
228 return mutatesCtxImpl(context, namespace, key, EFFECTIVE_MODEL);
232 public void apply(final InferenceAction action) {
233 Preconditions.checkState(this.action == null, "Action already defined to %s", this.action);
234 this.action = Preconditions.checkNotNull(action);
237 private abstract class AbstractPrerequisite<T> implements Prerequisite<T> {
238 private boolean done = false;
242 public final T resolve(final InferenceContext ctx) {
243 Preconditions.checkState(done);
244 Preconditions.checkArgument(ctx == ModifierImpl.this.ctx);
248 final boolean isDone() {
252 final boolean resolvePrereq(final T value) {
258 final <O> Prerequisite<O> transform(final Function<? super T, O> transformation) {
259 return ctx -> transformation.apply(resolve(ctx));
263 public final String toString() {
264 return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString();
267 ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
268 return toStringHelper.add("value", value);
272 private class PhaseMutation<C> extends AbstractPrerequisite<C> implements ContextMutation {
273 @SuppressWarnings("unchecked")
274 PhaseMutation(final StatementContextBase<?, ?, ?> context, final ModelProcessingPhase phase) {
275 context.addMutation(phase, this);
276 resolvePrereq((C) context);
280 public boolean isFinished() {
285 private class PhaseFinished<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C>
286 implements OnPhaseFinished {
287 @SuppressWarnings("unchecked")
289 public boolean phaseFinished(final StatementContextBase<?, ?, ?> context, final ModelProcessingPhase phase) {
290 return resolvePrereq((C) context);
294 private class NamespaceMutation<N extends IdentifierNamespace<?,?>>
295 extends AbstractPrerequisite<Mutable<?, ?, ?>> {
296 NamespaceMutation(final StatementContextBase<?, ?, ?> ctx, final Class<N> namespace) {
301 private class AddedToNamespace<C extends StmtContext<?,?,?>> extends AbstractPrerequisite<C>
302 implements OnNamespaceItemAdded, OnPhaseFinished {
303 private final ModelProcessingPhase phase;
305 AddedToNamespace(final ModelProcessingPhase phase) {
306 this.phase = requireNonNull(phase);
310 public void namespaceItemAdded(final StatementContextBase<?, ?, ?> context, final Class<?> namespace,
311 final Object key, final Object value) {
312 ((StatementContextBase<?, ?, ?>) value).addPhaseCompletedListener(phase, this);
315 @SuppressWarnings("unchecked")
317 public boolean phaseFinished(final StatementContextBase<?, ?, ?> context, final ModelProcessingPhase phase) {
318 return resolvePrereq((C) context);
322 ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
323 return super.addToStringAttributes(toStringHelper).add("phase", phase);
327 private class PhaseModificationInNamespace<C extends Mutable<?,?,?>> extends AbstractPrerequisite<C>
328 implements OnNamespaceItemAdded, ContextMutation {
329 private final ModelProcessingPhase modPhase;
331 PhaseModificationInNamespace(final ModelProcessingPhase phase) {
332 Preconditions.checkArgument(phase != null, "Model processing phase must not be null");
333 this.modPhase = phase;
336 @SuppressWarnings("unchecked")
338 public void namespaceItemAdded(final StatementContextBase<?, ?, ?> context, final Class<?> namespace,
339 final Object key, final Object value) {
340 StatementContextBase<?, ?, ?> targetCtx = contextImpl(value);
341 targetCtx.addMutation(modPhase, this);
342 resolvePrereq((C) targetCtx);
346 public boolean isFinished() {