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