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