/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.parser.spi.meta;
import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL;
import com.google.common.base.Supplier;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
/**
* Builder for effective model inference action.
*
* Model inference action is core principle of transforming
* declared model into effective model.
*
* Since YANG allows forward references, some inference actions
* need to be taken at a later point, where reference is actually
* resolved. Referenced objects are not retrieved directly
* but are represented as {@link Prerequisite} (prerequisite) for
* inference action to be taken.
*
* Some existing YANG statements are more complex and also object,
* for which effective model may be inferred is also represented
* as {@link Prerequisite} which once, when reference is available
* will contain target context, which may be used for inference
* action.
*
* <h2>Implementing inference action</h2>
*
* Effective inference action could always be splitted into two
* separate tasks:
* <ol>
* <li>Declaration of inference action and its prerequisites</li>
* <li>Execution of inference action</li>
* </ol>
* In order to declare inference action following steps needs
* to be taken:
*
* <ol>
* <li>Use {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)} to obtain
* {@link ModelActionBuilder}.
* <li>Use builder to specify concrete prerequisites of inference action
* (other statements, values from identifier namespaces)
* <li>Use builder to specify concrete set of nodes (or forward references to nodes)
* which will inference action mutate.
* <li>Use {@link #apply(InferenceAction)} with {@link InferenceAction} implementation
* to register inference action.
* </ol>
*
* Action will be executed when:
* <ul>
* <li> {@link InferenceAction#apply()} - all prerequisites (and declared forward references) are met,
* action could dereference them and start applying changes.
* </li>
* <li>{@link InferenceAction#prerequisiteFailed(Collection)} - semantic parser finished all other satisfied
* inference actions and some of declared prerequisites was still not met.
* </li>
* </ul>
*
* TODO: Insert real word example
*
* <h2>Design notes</h2>
* {@link java.util.concurrent.Future} seems as viable and more standard
* alternative to {@link Prerequisite}, but futures also carries
* promise that resolution of it is carried in other
* thread, which will actually put additional constraints on
* semantic parser.
*
* Also listening on multiple futures is costly, so we opted
* out of future and designed API, which later may introduce
* futures.
*
*/
public interface ModelActionBuilder {
@FunctionalInterface
interface Prerequisite<T> extends Supplier<T> {
/**
* Returns associated prerequisite once it is resolved.
*
* @return associated prerequisite once it is resolved.
*/
@Override
T get();
}
/**
* User-defined inference action.
*
*/
interface InferenceAction {
/**
* Invoked once all prerequisites were met and forward references
* were resolved and inference action should be applied.
*
* Implementors may do necessary changes to mutable objects
* which were declared.
*
* @throws InferenceException If inference action can not be processed.
* Note that this exception be used for user to debug YANG sources,
* so should provide helpful context to fix issue in sources.
*/
void apply() throws InferenceException;
/**
* Invoked once one of prerequisites was not met,
* even after all other satisfiable inference actions were processed.
*
* Implementors MUST throw {@link InferenceException} if semantic processing
* of model should be stopped and failed.
*
* List of failed prerequisites should be used to select right message / error
* type to debug problem in YANG sources.
*
* @param failed collection of prerequisites which were not met
* @throws InferenceException If inference action can not be processed.
* Note that this exception be used for user to debug YANG sources,
* so should provide helpful context to fix issue in sources.
*/
void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) throws InferenceException;
}
/**
* Action requires that the specified context transition to complete{@link ModelProcessingPhase#FULL_DECLARATION}
* phase.
*
* @param context Statement context which needs to
* @return A {@link Prerequisite} returning the declared statement of the specified context.
*/
@Nonnull <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(StmtContext<?, ? extends D, ?> context);
@Nonnull <A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
Prerequisite<StmtContext<A, D, E>> requiresCtx(StmtContext<A, D, E> context, ModelProcessingPhase phase);
@Nonnull <K, N extends StatementNamespace<K, ?, ? >> Prerequisite<StmtContext<?,?,?>> requiresCtx(
StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase);
default @Nonnull <T extends Mutable<?, ?, ?>> Prerequisite<T> mutatesEffectiveCtx(final T stmt) {
return mutatesCtx(stmt, EFFECTIVE_MODEL);
}
@Nonnull <K, E extends EffectiveStatement<?, ?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>>
Prerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
@Nonnull <C extends StmtContext.Mutable<?, ?, ?>, CT extends C> Prerequisite<C> mutatesCtx(CT root,
ModelProcessingPhase phase);
void apply(InferenceAction action) throws InferenceException;
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
Prerequisite<D> requiresDeclared(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
Prerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(
StmtContext<?, ?, ? extends E> stmt);
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
Prerequisite<E> requiresEffective(StmtContext<?, ?, ?> context, Class<N> namespace, K key);
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
Prerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(StmtContext<?, ?, ?> context, Class<N> namespace,
K key);
/**
* @deprecated Undocumented method. Use at your own risk.
*/
@Deprecated
@Nonnull <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?,?,?>> mutatesNs(
Mutable<?,?, ?> ctx, Class<N> namespace);
}