Add support for incremental Prerequisites
[yangtools.git] / yang / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / ModelActionBuilder.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.spi.meta;
9
10 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL;
11
12 import java.util.Collection;
13 import javax.annotation.Nonnull;
14 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
15 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
16 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
17 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
18
19 /**
20  * Builder for effective model inference action. Model inference action is core principle of transforming
21  * declared model into effective model.
22  *
23  * <p>
24  * Since YANG allows forward references, some inference actions need to be taken at a later point, where reference is
25  * actually resolved. Referenced objects are not retrieved directly but are represented as {@link Prerequisite}
26  * (prerequisite) for inference action to be taken.
27  *
28  * <p>
29  * Some existing YANG statements are more complex and also object, for which effective model may be inferred is also
30  * represented as a {@link Prerequisite} which, when reference is available, will contain target context, which may be
31  * used for inference action.
32  *
33  * <h2>Implementing inference action</h2>
34  * Effective inference action could always be splitted into two separate tasks:
35  * <ol>
36  * <li>Declaration of inference action and its prerequisites</li>
37  * <li>Execution of inference action</li>
38  * </ol>
39  *
40  * <p>
41  * In order to declare inference action following steps needs
42  * to be taken:
43  * <ol>
44  * <li>Use {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)} to obtain
45  * {@link ModelActionBuilder}.
46  * <li>Use builder to specify concrete prerequisites of inference action
47  * (other statements, values from identifier namespaces)
48  * <li>Use builder to specify concrete set of nodes (or forward references to nodes)
49  * which will inference action mutate.
50  * <li>Use {@link #apply(InferenceAction)} with {@link InferenceAction} implementation
51  * to register inference action.
52  * </ol>
53  *
54  * <p>
55  * An action will be executed when:
56  * <ul>
57  * <li> {@link InferenceAction#apply(InferenceContext)} - all prerequisites (and declared forward references) are met,
58  * action could dereference them and start applying changes.
59  * </li>
60  * <li>{@link InferenceAction#prerequisiteFailed(Collection)} - semantic parser finished all other satisfied
61  * inference actions and some of declared prerequisites was still not met.
62  * </li>
63  * </ul>
64  *
65  * <p>
66  * TODO: Insert real word example
67  *
68  * <h2>Design notes</h2>
69  * {@link java.util.concurrent.Future} seems as viable and more standard alternative to {@link Prerequisite}, but
70  * Futures also carries promise that resolution of it is carried in other thread, which will actually put additional
71  * constraints on semantic parser.
72  *
73  * <p>
74  * Also listening on multiple futures is costly, so we opted out of future and designed API, which later may introduce
75  * futures.
76  */
77 public interface ModelActionBuilder {
78     interface InferenceContext {
79
80     }
81
82     @FunctionalInterface
83     interface Prerequisite<T> {
84         /**
85          * Returns associated prerequisite once it is resolved.
86          *
87          * @param ctx Inference context in which the prerequisite was satisfied
88          * @return associated prerequisite once it is resolved.
89          */
90         T resolve(InferenceContext ctx);
91     }
92
93     /**
94      * User-defined inference action.
95      */
96     interface InferenceAction {
97
98         /**
99          * Invoked once all prerequisites were met and forward references were resolved and inference action should be
100          * applied. Implementors may perform necessary changes to mutable objects which were declared.
101          *
102          * @throws InferenceException If inference action can not be processed. Note that this exception be used for
103          *         user to debug YANG sources, so should provide helpful context to fix issue in sources.
104          */
105         void apply(InferenceContext ctx);
106
107         /**
108          * Invoked once one of prerequisites was not met, even after all other satisfiable inference actions were
109          * processed.
110          *
111          * <p>
112          * Implementors MUST throw {@link InferenceException} if semantic processing of model should be stopped
113          * and failed.
114          *
115          * <p>
116          * List of failed prerequisites should be used to select right message / error type to debug problem in YANG
117          * sources.
118          *
119          * @param failed collection of prerequisites which were not met
120          * @throws InferenceException If inference action can not be processed. Note that this exception be used
121          *                            by user to debug YANG sources, hence it should provide helpful context to fix
122          *                            the issue in sources.
123          */
124         void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed);
125     }
126
127     /**
128      * Action requires that the specified context transition to complete {@link ModelProcessingPhase#FULL_DECLARATION}
129      * phase and produce a declared statement.
130      *
131      * @param context Statement context which needs to complete the transition.
132      * @return A {@link Prerequisite} returning the declared statement of the requested context.
133      */
134     @Nonnull <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(StmtContext<?, ? extends D, ?> context);
135
136     /**
137      * Create a requirement on specified statement to be declared.
138      *
139      * @deprecated Undocumented method. Use at your own risk.
140      */
141     @Deprecated
142     @Nonnull <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
143         Prerequisite<D> requiresDeclared(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
144
145     /**
146      * Action requires that the specified context completes specified phase before {@link #apply(InferenceAction)}
147      * may be invoked.
148      *
149      * @param context Statement context which needs to complete the transition.
150      * @param phase ModelProcessingPhase which must have completed
151      * @return A {@link Prerequisite} returning the requested context.
152      */
153     @Nonnull <A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
154         Prerequisite<StmtContext<A, D, E>> requiresCtx(StmtContext<A, D, E> context, ModelProcessingPhase phase);
155
156     @Nonnull <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
157         StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase);
158
159     @Nonnull <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
160             StmtContext<?, ?, ?> context, Class<N> namespace, NamespaceKeyCriterion<K> criterion,
161             ModelProcessingPhase phase);
162
163     /**
164      * Action mutates the effective model of specified statement. This is a shorthand for
165      * {@code mutatesCtx(context, EFFECTIVE_MODEL}.
166      *
167      * @param context Target statement context
168      * @return A {@link Prerequisite} returning the requested context.
169      */
170     default @Nonnull <T extends Mutable<?, ?, ?>> Prerequisite<T> mutatesEffectiveCtx(final T context) {
171         return mutatesCtx(context, EFFECTIVE_MODEL);
172     }
173
174     @Nonnull <K, E extends EffectiveStatement<?, ?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>>
175         Prerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
176
177     default @Nonnull <K, E extends EffectiveStatement<?, ?>,
178             N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> Prerequisite<Mutable<?, ?, E>>
179                 mutatesEffectiveCtxPath(StmtContext<?, ?, ?> context, Class<N> namespace, Iterable<K> keys) {
180         throw new UnsupportedOperationException(getClass() + " does not implement mutatesEffectiveCtxPath()");
181     }
182
183     /**
184      * Action mutates the specified statement in the specified phase. Target statement cannot complete specified
185      * phase before this action is applier.
186      *
187      * @param context Target statement context
188      * @return A {@link Prerequisite} returning the requested context.
189      */
190     @Nonnull <C extends Mutable<?, ?, ?>, T extends C> Prerequisite<C> mutatesCtx(T context,
191             ModelProcessingPhase phase);
192
193     /**
194      * Apply an {@link InferenceAction} when this action's prerequisites are resolved.
195      *
196      * @param action Inference action to apply
197      * @throws InferenceException if the action fails
198      * @throws NullPointerException if {@code action is null}
199      * @throws IllegalStateException if this action has an inference action already associated.
200      */
201     void apply(InferenceAction action);
202
203     /**
204      * Create a requirement on specified statement context to be declared.
205      *
206      * @deprecated Undocumented method. Use at your own risk.
207      */
208     @Deprecated
209     @Nonnull <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
210         Prerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
211
212     /**
213      * Create a requirement on specified statement to become effective.
214      *
215      * @deprecated Undocumented method. Use at your own risk.
216      */
217     @Deprecated
218     @Nonnull <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(
219             StmtContext<?, ?, ? extends E> stmt);
220
221     /**
222      * Create a requirement on specified statement to become effective.
223      *
224      * @deprecated Undocumented method. Use at your own risk.
225      */
226     @Deprecated
227     @Nonnull <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
228         Prerequisite<E> requiresEffective(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
229
230     /**
231      * Create a requirement on specified statement context to become effective.
232      *
233      * @deprecated Undocumented method. Use at your own risk.
234      */
235     @Deprecated
236     @Nonnull <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
237     Prerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(StmtContext<?, ?, ?> context, Class<N> namespace,
238             K key);
239
240     /**
241      * Mark the fact that this action is mutating a namespace.
242      *
243      * @deprecated Undocumented method. Use at your own risk.
244      */
245     @Deprecated
246     @Nonnull <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?,?,?>> mutatesNs(
247             Mutable<?,?, ?> ctx, Class<N> namespace);
248 }