2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.spi.meta;
10 import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL;
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;
22 * Builder for effective model inference action. Model inference action is core principle of transforming
23 * declared model into effective model.
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.
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.
35 * <h2>Implementing inference action</h2>
36 * Effective inference action could always be splitted into two separate tasks:
38 * <li>Declaration of inference action and its prerequisites</li>
39 * <li>Execution of inference action</li>
43 * In order to declare inference action following steps needs
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.
57 * An action will be executed when:
59 * <li> {@link InferenceAction#apply(InferenceContext)} - all prerequisites (and declared forward references) are met,
60 * action could dereference them and start applying changes.
62 * <li>{@link InferenceAction#prerequisiteFailed(Collection)} - semantic parser finished all other satisfied
63 * inference actions and some of declared prerequisites was still not met.
68 * TODO: Insert real word example
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.
76 * Also listening on multiple futures is costly, so we opted out of future and designed API, which later may introduce
79 public interface ModelActionBuilder {
80 interface InferenceContext {
85 interface Prerequisite<T> {
87 * Returns associated prerequisite once it is resolved.
89 * @param ctx Inference context in which the prerequisite was satisfied
90 * @return associated prerequisite once it is resolved.
92 T resolve(InferenceContext ctx);
96 * User-defined inference action.
98 interface InferenceAction {
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.
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.
107 void apply(InferenceContext ctx);
110 * Invoked once one of prerequisites was not met, even after all other satisfiable inference actions were
114 * Implementors MUST throw {@link InferenceException} if semantic processing of model should be stopped
118 * List of failed prerequisites should be used to select right message / error type to debug problem in YANG
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.
126 void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed);
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.
133 * The default implementation invokes {@link #prerequisiteFailed(Collection)}, implementations should override
134 * this method if they wish, for example, to ignore the missing prerequisite.
136 * @param unavail Unavailable prerequisite
139 default void prerequisiteUnavailable(final Prerequisite<?> unavail) {
140 prerequisiteFailed(ImmutableList.of(unavail));
145 * Action requires that the specified context transition to complete {@link ModelProcessingPhase#FULL_DECLARATION}
146 * phase and produce a declared statement.
148 * @param context Statement context which needs to complete the transition.
149 * @return A {@link Prerequisite} returning the declared statement of the requested context.
151 <D extends DeclaredStatement<?>> @NonNull Prerequisite<D> requiresDeclared(StmtContext<?, ? extends D, ?> context);
154 * Create a requirement on specified statement to be declared.
156 * @deprecated Undocumented method. Use at your own risk.
159 <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
160 @NonNull Prerequisite<D> requiresDeclared(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
163 * Action requires that the specified context completes specified phase before {@link #apply(InferenceAction)}
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.
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);
173 <K, N extends StatementNamespace<K, ?, ?>> @NonNull Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
174 StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase);
176 <K, N extends StatementNamespace<K, ?, ?>> @NonNull Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
177 StmtContext<?, ?, ?> context, Class<N> namespace, NamespaceKeyCriterion<K> criterion,
178 ModelProcessingPhase phase);
181 * Action mutates the effective model of specified statement. This is a shorthand for
182 * {@code mutatesCtx(context, EFFECTIVE_MODEL}.
184 * @param context Target statement context
185 * @return A {@link Prerequisite} returning the requested context.
187 default <T extends Mutable<?, ?, ?>> @NonNull Prerequisite<T> mutatesEffectiveCtx(final T context) {
188 return mutatesCtx(context, EFFECTIVE_MODEL);
191 <K, E extends EffectiveStatement<?, ?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>>
192 @NonNull Prerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(StmtContext<?, ?, ?> context, Class<N> namespace,
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()");
202 * Action mutates the specified statement in the specified phase. Target statement cannot complete specified
203 * phase before this action is applier.
205 * @param context Target statement context
206 * @return A {@link Prerequisite} returning the requested context.
208 <C extends Mutable<?, ?, ?>, T extends C> @NonNull Prerequisite<C> mutatesCtx(T context,
209 ModelProcessingPhase phase);
212 * Apply an {@link InferenceAction} when this action's prerequisites are resolved.
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.
219 void apply(InferenceAction action);
222 * Create a requirement on specified statement context to be declared.
224 * @deprecated Undocumented method. Use at your own risk.
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);
232 * Create a requirement on specified statement to become effective.
234 * @deprecated Undocumented method. Use at your own risk.
237 <E extends EffectiveStatement<?, ?>> @NonNull Prerequisite<E> requiresEffective(
238 StmtContext<?, ?, ? extends E> stmt);
241 * Create a requirement on specified statement to become effective.
243 * @deprecated Undocumented method. Use at your own risk.
246 <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
247 @NonNull Prerequisite<E> requiresEffective(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
250 * Create a requirement on specified statement context to become effective.
252 * @deprecated Undocumented method. Use at your own risk.
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);
260 * Mark the fact that this action is mutating a namespace.
262 * @deprecated Undocumented method. Use at your own risk.
265 <N extends IdentifierNamespace<?, ?>> @NonNull Prerequisite<Mutable<?,?,?>> mutatesNs(Mutable<?,?, ?> ctx,