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