Merge "Fixed sonar issues in ClassLoaderUtils."
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / ModifierImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
9
10 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL;
11 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.FULL_DECLARATION;
12
13 import com.google.common.base.Function;
14 import com.google.common.base.Preconditions;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.Set;
18 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
19 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
20 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
28 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
29 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextMutation;
30 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnNamespaceItemAdded;
31 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnPhaseFinished;
32
33 class ModifierImpl implements ModelActionBuilder {
34
35     private final ModelProcessingPhase phase;
36     private final Set<AbstractPrerequisite<?>> unsatisfied = new HashSet<>();
37     private final Set<AbstractPrerequisite<?>> mutations = new HashSet<>();
38
39     private InferenceAction action;
40     private boolean actionApplied = false;
41
42     ModifierImpl(ModelProcessingPhase phase) {
43         this.phase = Preconditions.checkNotNull(phase);
44     }
45
46     private <D> AbstractPrerequisite<D> addReq(AbstractPrerequisite<D> prereq) {
47         unsatisfied.add(prereq);
48         return prereq;
49     }
50
51     private <T> AbstractPrerequisite<T> addMutation(AbstractPrerequisite<T> mutation) {
52         mutations.add(mutation);
53         return mutation;
54     }
55
56
57
58     private void checkNotRegistered() {
59         Preconditions.checkState(action == null, "Action was already registered.");
60     }
61
62     private IllegalStateException shouldNotHappenProbablyBug(SourceException e) {
63         return new IllegalStateException("Source exception during registering prerequisite. This is probably bug.",e);
64     }
65
66     private void tryToResolve() throws InferenceException {
67         if(action == null || isApplied()) {
68             // Action was not yet defined
69             return;
70         }
71         if(removeSatisfied()) {
72             applyAction();
73         }
74     }
75
76     private boolean removeSatisfied() {
77         Iterator<AbstractPrerequisite<?>> prereq = unsatisfied.iterator();
78         boolean allSatisfied = true;
79         while(prereq.hasNext()) {
80             if(prereq.next().isDone()) {
81                 // We are removing current prerequisite from list.
82                 prereq.remove();
83             } else {
84                 allSatisfied  = false;
85             }
86         }
87         return allSatisfied;
88     }
89
90     ModelProcessingPhase getPhase() {
91         return phase;
92     }
93
94     boolean isApplied() {
95
96         return actionApplied;
97     }
98
99     void failModifier() throws InferenceException {
100         removeSatisfied();
101         action.prerequisiteFailed(unsatisfied);
102         action = null;
103     }
104
105     private void applyAction() throws InferenceException {
106
107         try {
108             action.apply();
109         } catch (InferenceException e) {
110             actionApplied = false;
111             return;
112         }
113         //  Mark all mutations as performed, so context node could move to next.
114         actionApplied = true;
115     }
116
117     @SuppressWarnings({ "unchecked", "rawtypes" })
118     private <K, C extends StmtContext<?,?,?>, N extends StatementNamespace<K, ?, ?>> AbstractPrerequisite<C> requiresCtxImpl(StmtContext<?, ?, ?> context, Class<N> namespace, K key,ModelProcessingPhase phase)  {
119         checkNotRegistered();
120         try {
121             AddedToNamespace<C> addedToNs = new AddedToNamespace<C>(phase);
122             addReq(addedToNs);
123             contextImpl(context).onNamespaceItemAddedAction((Class) namespace,key,addedToNs);
124             return addedToNs;
125         } catch (SourceException e) {
126             throw shouldNotHappenProbablyBug(e);
127         }
128     }
129
130     private <C extends StmtContext<?, ?, ?>> AbstractPrerequisite<C> requiresCtxImpl(C context, ModelProcessingPhase phase) {
131         Preconditions.checkState(action == null, "Action was already registered.");
132         try {
133             PhaseFinished<C> phaseFin = new PhaseFinished<C>();
134             addReq(phaseFin);
135             contextImpl(context).addPhaseCompletedListener(phase,phaseFin);
136             return phaseFin;
137         } catch (SourceException e) {
138             throw shouldNotHappenProbablyBug(e);
139         }
140     }
141
142     @SuppressWarnings({ "rawtypes", "unchecked" })
143     private <K, C extends StmtContext.Mutable<?, ?, ?> , N extends StatementNamespace<K, ?, ? >> AbstractPrerequisite<C> mutatesCtxImpl(
144                 StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase) {
145             try {
146                 PhaseModificationInNamespace<C> mod = new PhaseModificationInNamespace<C>(phase);
147                 addMutation(mod);
148                 contextImpl(context).onNamespaceItemAddedAction((Class) namespace,key,mod);
149                 return mod;
150             } catch (SourceException e) {
151                 throw shouldNotHappenProbablyBug(e);
152             }
153         }
154
155     private static StatementContextBase<?,?,?> contextImpl(StmtContext<?,?,?> context) {
156         Preconditions.checkArgument(context instanceof StatementContextBase,"Supplied context was not provided by this reactor.");
157         return StatementContextBase.class.cast(context);
158     }
159
160     @Override
161     public <C extends Mutable<?, ?, ?>, CT extends C> Prerequisite<C> mutatesCtx(CT context, ModelProcessingPhase phase) {
162         try {
163             return addMutation(new PhaseMutation<C>(contextImpl(context),phase));
164         } catch (InferenceException e) {
165             throw shouldNotHappenProbablyBug(e);
166         }
167     }
168
169     @Override
170     public  <A,D extends DeclaredStatement<A>,E extends EffectiveStatement<A, D>> AbstractPrerequisite<StmtContext<A, D, E>> requiresCtx(StmtContext<A, D, E> context, ModelProcessingPhase phase) {
171         return requiresCtxImpl(context, phase);
172     }
173
174
175     @Override
176     public <K, N extends StatementNamespace<K, ?, ? >> Prerequisite<StmtContext<?,?,?>> requiresCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase) {
177         return requiresCtxImpl(context, namespace, key, phase);
178     }
179
180     @Override
181     public <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(StmtContext<?, ? extends D, ?> context) {
182         return requiresCtxImpl(context, FULL_DECLARATION).transform(StmtContextUtils.<D>buildDeclared());
183     }
184
185     @Override
186     public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> AbstractPrerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(
187             StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
188         return requiresCtxImpl(context, namespace, key, FULL_DECLARATION);
189     }
190
191     @Override
192     public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> Prerequisite<D> requiresDeclared(
193             StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
194         final AbstractPrerequisite<StmtContext<?,D,?>> rawContext = requiresCtxImpl(context, namespace, key, FULL_DECLARATION);
195         return rawContext.transform(StmtContextUtils.<D>buildDeclared());
196     }
197
198     @Override
199     public <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(StmtContext<?, ?, ? extends E> stmt) {
200         return requiresCtxImpl(stmt, EFFECTIVE_MODEL).transform(StmtContextUtils.<E>buildEffective());
201     }
202
203     @Override
204     public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> AbstractPrerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(
205             StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
206         return requiresCtxImpl(contextImpl(context),namespace,key, EFFECTIVE_MODEL);
207     }
208
209     @Override
210     public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> Prerequisite<E> requiresEffective(
211             StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
212         final AbstractPrerequisite<StmtContext<?,?,E>> rawContext = requiresCtxImpl(context, namespace, key, EFFECTIVE_MODEL);
213         return rawContext.transform(StmtContextUtils.<E>buildEffective());
214     }
215
216
217     @Override
218     public <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?, ?, ?>> mutatesNs(Mutable<?, ?, ?> context,
219             Class<N> namespace) {
220         try {
221             return addMutation(new NamespaceMutation<N>(contextImpl(context),namespace));
222         } catch (SourceException e) {
223             throw shouldNotHappenProbablyBug(e);
224         }
225     }
226
227     @Override
228     public <T extends Mutable<?, ?, ?>> Prerequisite<T> mutatesEffectiveCtx(T stmt) {
229         return mutatesCtx(stmt, EFFECTIVE_MODEL);
230     }
231
232
233    @Override
234     public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> AbstractPrerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(
235             StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
236         return mutatesCtxImpl(context, namespace, key, EFFECTIVE_MODEL);
237     }
238
239
240
241     @Override
242     public void apply(InferenceAction action) throws InferenceException {
243         this.action = Preconditions.checkNotNull(action);
244         tryToResolve();
245     }
246
247     private abstract class AbstractPrerequisite<T> implements Prerequisite<T> {
248
249         private T value;
250         private boolean done = false;
251
252         @Override
253         public T get() {
254             Preconditions.checkState(isDone());
255             return value;
256         }
257
258         @Override
259         public boolean isDone() {
260             return done;
261         }
262
263         protected boolean resolvePrereq(T value) throws InferenceException {
264             this.value = value;
265             this.done = true;
266             tryToResolve();
267             return isApplied();
268         }
269
270         protected <O> Prerequisite<O> transform(final Function<? super T,O> transformation) {
271
272             return new Prerequisite<O>() {
273
274                 @Override
275                 public O get() {
276                     return transformation.apply(AbstractPrerequisite.this.get());
277                 }
278
279                 @Override
280                 public boolean isDone() {
281                     return AbstractPrerequisite.this.isDone();
282                 }
283
284             };
285         }
286
287     }
288
289     private class PhaseMutation<C> extends AbstractPrerequisite<C> implements ContextMutation {
290
291         @SuppressWarnings("unchecked")
292         public PhaseMutation(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws InferenceException {
293             context.addMutation(phase, this);
294             resolvePrereq((C) context);
295         }
296
297         @Override
298         public boolean isFinished() {
299             return isApplied();
300         }
301
302
303     }
304     private class PhaseFinished<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C> implements OnPhaseFinished {
305
306         @SuppressWarnings("unchecked")
307         @Override
308         public boolean phaseFinished(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws SourceException {
309             return resolvePrereq((C) (context));
310         }
311     }
312
313     private class NamespaceMutation<N extends IdentifierNamespace<?,?>> extends  AbstractPrerequisite<StmtContext.Mutable<?, ?, ?>>  {
314
315         public NamespaceMutation(StatementContextBase<?, ?, ?> ctx, Class<N> namespace) throws InferenceException {
316             resolvePrereq(ctx);
317         }
318
319     }
320
321     private class AddedToNamespace<C extends StmtContext<?,?,?>> extends  AbstractPrerequisite<C> implements OnNamespaceItemAdded,OnPhaseFinished {
322
323         private final ModelProcessingPhase phase;
324
325         public <K, N extends StatementNamespace<K, ?, ?>> AddedToNamespace(ModelProcessingPhase phase) {
326             this.phase = phase;
327         }
328
329         @Override
330         public void namespaceItemAdded(StatementContextBase<?, ?, ?> context, Class<?> namespace, Object key,
331                 Object value) throws SourceException {
332             StatementContextBase<?, ?, ?> targetContext = (StatementContextBase<?, ?, ?>) value;
333             targetContext.addPhaseCompletedListener(phase, this);
334         }
335
336         @SuppressWarnings("unchecked")
337         @Override
338         public boolean phaseFinished(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws SourceException {
339             return resolvePrereq((C) context);
340         }
341
342     }
343
344     private class PhaseModificationInNamespace<C extends Mutable<?,?,?>> extends AbstractPrerequisite<C> implements OnNamespaceItemAdded, ContextMutation {
345
346         private final ModelProcessingPhase modPhase;
347
348         public <K, N extends StatementNamespace<K, ?, ?>> PhaseModificationInNamespace(ModelProcessingPhase phase) throws SourceException {
349             Preconditions.checkArgument(phase != null, "Model processing phase must not be null");
350             this.modPhase = phase;
351         }
352
353         @SuppressWarnings("unchecked")
354         @Override
355         public void namespaceItemAdded(StatementContextBase<?, ?, ?> context, Class<?> namespace, Object key,
356                 Object value) throws SourceException {
357             context.addMutation(modPhase,this);
358             resolvePrereq((C) context);
359         }
360
361         @Override
362         public boolean isFinished() {
363             return isApplied();
364         }
365     }
366
367 }