Separate out StatementSupport.applyCopyPolicy()
[yangtools.git] / yang / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / StatementSupport.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 com.google.common.annotations.Beta;
11 import java.util.Optional;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.eclipse.jdt.annotation.Nullable;
14 import org.opendaylight.yangtools.yang.common.QName;
15 import org.opendaylight.yangtools.yang.common.QNameModule;
16 import org.opendaylight.yangtools.yang.model.api.meta.ArgumentDefinition;
17 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
18 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
19 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
21 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
22
23 /**
24  * Support for processing concrete YANG statement.
25  *
26  * <p>
27  * This interface is intended to be implemented by developers, which want to introduce support of statement to parser.
28  * Consider subclassing {@link AbstractStatementSupport} for easier implementation of this interface.
29  *
30  * @param <A> Argument type
31  * @param <D> Declared Statement representation
32  * @param <E> Effective Statement representation
33  */
34 public interface StatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
35         extends StatementDefinition, StatementFactory<A, D, E> {
36     /**
37      * Returns public statement definition, which will be present in built statements.
38      *
39      * <p>
40      * Public statement definition may be used to provide different implementation of statement definition,
41      * which will not retain any build specific data or context.
42      *
43      * @return public statement definition, which will be present in built statements.
44      */
45     @NonNull StatementDefinition getPublicView();
46
47     /**
48      * Parses textual representation of argument in object representation.
49      *
50      * @param ctx Context, which may be used to access source-specific namespaces required for parsing.
51      * @param value String representation of value, as was present in text source.
52      * @return Parsed value
53      * @throws SourceException when an inconsistency is detected.
54      */
55     A parseArgumentValue(StmtContext<?, ?, ?> ctx, String value);
56
57     /**
58      * Adapts the argument value to match a new module.
59      *
60      * @param ctx Context, which may be used to access source-specific namespaces required for parsing.
61      * @param targetModule Target module, may not be null.
62      * @return Adapted argument value. The default implementation returns original value stored in context.
63      */
64     default A adaptArgumentValue(final StmtContext<A, D, E> ctx, final QNameModule targetModule) {
65         return ctx.argument();
66     }
67
68     /**
69      * Invoked when a statement supported by this instance is added to build context. This allows implementations
70      * of this interface to start tracking the statement and perform any modifications to the build context hierarchy,
71      * accessible via {@link StmtContext#getParentContext()}. One such use is populating the parent's namespaces to
72      * allow it to locate this child statement.
73      *
74      * @param stmt Context of added statement. No substatements are available.
75      */
76     void onStatementAdded(StmtContext.Mutable<A, D, E> stmt);
77
78     /**
79      * Invoked when statement is closed during {@link ModelProcessingPhase#SOURCE_PRE_LINKAGE} phase, only substatements
80      * from this and previous phase are available.
81      *
82      * <p>
83      * Implementation may use method to perform actions on this event or register modification action using
84      * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
85      *
86      * @param stmt Context of added statement.
87      */
88     void onPreLinkageDeclared(StmtContext.Mutable<A, D, E> stmt);
89
90     /**
91      * Invoked when statement is closed during {@link ModelProcessingPhase#SOURCE_LINKAGE} phase, only substatements
92      * from this and previous phase are available.
93      *
94      * <p>
95      * Implementation may use method to perform actions on this event or register modification action using
96      * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
97      *
98      * @param stmt Context of added statement.
99      * @throws SourceException when an inconsistency is detected.
100      */
101     void onLinkageDeclared(StmtContext.Mutable<A, D, E> stmt);
102
103     /**
104      * Invoked when statement is closed during {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase,
105      * only substatements from this phase are available.
106      *
107      * <p>
108      * Implementation may use method to perform actions on this event or register modification action using
109      * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
110      *
111      * @param stmt Context of added statement. Argument and statement parent is accessible.
112      * @throws SourceException when an inconsistency is detected.
113      */
114     void onStatementDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt);
115
116     /**
117      * Invoked when statement is closed during {@link ModelProcessingPhase#FULL_DECLARATION} phase,
118      * only substatements from this phase are available.
119      *
120      * <p>
121      * Implementation may use method to perform actions on this event or register modification action using
122      * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
123      *
124      * @param stmt Context of added statement. Argument and statement parent is accessible.
125      * @throws SourceException when an inconsistency is detected.
126      */
127     void onFullDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt);
128
129     /**
130      * Returns true if this support has argument specific supports.
131      */
132     boolean hasArgumentSpecificSupports();
133
134     /**
135      * If this support has argument specific supports, the method returns support specific for given argument
136      * (e.g. type statement support need to be specialized based on its argument), otherwise returns null.
137      *
138      * @param argument argument of statement
139      * @return statement support specific for supplied argument or null
140      */
141     @Nullable StatementSupport<?, ?, ?> getSupportSpecificForArgument(String argument);
142
143     /**
144      * Return this statement's {@link CopyPolicy}. This is a static value, reflecting how this statement reacts to being
145      * replicated to a different context, without reflecting on behaviour of potential substatements, which would come
146      * into play in something like:
147      *
148      * <pre>
149      *   <code>
150      *     module foo {
151      *       namespace foo;
152      *       prefix foo;
153      *
154      *       extension note {
155      *         argument string {
156      *           type string {
157      *             length 1..max;
158      *           }
159      *         }
160      *         description "Can be used in description/reference statements to attach additional notes";
161      *       }
162      *
163      *       description "A nice module extending description statement semantics" {
164      *         foo:note "We can now attach description/reference a note.";
165      *         foo:note "Also another note";
166      *       }
167      *     }
168      *   </code>
169      * </pre>
170      *
171      * <p>
172      * In this scenario, it is the reactor's job to figure out what to do (like talking to substatements).
173      *
174      * @return This statement's copy policy
175      */
176     @NonNull CopyPolicy copyPolicy();
177
178     /**
179      * Determine reactor copy behaviour of a statement instance. Statement support classes are required to determine
180      * their operations with regard to their statements being replicated into different contexts, so that
181      * {@link Mutable} instances are not created when it is evident they are superfluous.
182      *
183      * <p>
184      * The copy operation has three intrinsic parts:
185      * <ul>
186      *   <li>target {@code parent}, i.e. new parent statement for the copy. This determines things like default value
187      *       of the {@code config} statement and similar</li>
188      *   <li>copy operation type</li>
189      *   <li>{@code target module}, which defines the default namespace for the statement copy. This might not be always
190      *       present, in which case the namespace is retained from the source. As an example, {@code uses} changes
191      *       the default namespace to parent's namespace, whereas {@code augment} does not.</li>
192      * </ul>
193      *
194      * <p>
195      * Implementations should return the context to use -- returning {@code stmt} if there is no change or a copy of it.
196      *
197      * @param stmt Context of statement to be copied statement
198      * @param parent Parent statement context
199      * @param copyType Type of copy being performed
200      * @param targetModule Target module, if present
201      * @return StmtContext holding the effective state
202      */
203     @NonNull StmtContext<?, ?, ?> effectiveCopyOf(StmtContext<?, ?, ?> stmt, Mutable<?, ?, ?> parent, CopyType copyType,
204         @Nullable QNameModule targetModule);
205
206     /**
207      * Given a raw string representation of an argument, try to use a shared representation.
208      *
209      * @param rawArgument Argument string
210      * @return A potentially-shard instance
211      */
212     default String internArgument(final String rawArgument) {
213         return rawArgument;
214     }
215
216     /**
217      * Returns unknown statement form of a regular YANG statement supplied as a parameter to the method.
218      *
219      * @param yangStmtDef statement definition of a regular YANG statement
220      * @return Optional of unknown statement form of a regular YANG statement or empty() if it is not supported by this
221      *         statement support
222      */
223     default Optional<StatementSupport<?, ?, ?>> getUnknownStatementDefinitionOf(final StatementDefinition yangStmtDef) {
224         return Optional.empty();
225     }
226
227     /**
228      * Returns true if this statement support and all its substatements ignore if-feature statements (e.g. yang-data
229      * extension defined in <a href="https://tools.ietf.org/html/rfc8040#section-8">RFC 8040</a>). Default
230      * implementation returns false.
231      *
232      * @return true if this statement support ignores if-feature statements,
233      *         otherwise false.
234      */
235     @Beta
236     default boolean isIgnoringIfFeatures() {
237         return false;
238     }
239
240     /**
241      * Returns true if this statement support and all its substatements ignore config statements (e.g. yang-data
242      * extension defined in <a href="https://tools.ietf.org/html/rfc8040#section-8">RFC 8040</a>). Default
243      * implementation returns false.
244      *
245      * @return true if this statement support ignores config statements,
246      *         otherwise false.
247      */
248     @Beta
249     default boolean isIgnoringConfig() {
250         return false;
251     }
252
253     @Override
254     default QName getStatementName() {
255         return getPublicView().getStatementName();
256     }
257
258     @Override
259     default @NonNull Optional<ArgumentDefinition> getArgumentDefinition() {
260         return getPublicView().getArgumentDefinition();
261     }
262
263     @Override
264     default Class<? extends DeclaredStatement<?>> getDeclaredRepresentationClass() {
265         return getPublicView().getDeclaredRepresentationClass();
266     }
267
268     @Override
269     default Class<? extends EffectiveStatement<?,?>> getEffectiveRepresentationClass() {
270         return getPublicView().getEffectiveRepresentationClass();
271     }
272
273     /**
274      * Statement context copy policy, indicating how should reactor handle statement copy operations. Every statement
275      * copied by the reactor is subject to policy check done by
276      * {@link StatementSupport#effectiveCopyOf(StmtContext, Mutable, CopyType, QNameModule)}.
277      */
278     enum CopyPolicy {
279         /**
280          * Reuse the source statement context in the new place, as it cannot be affected by any further operations. This
281          * implies that the semantics of the effective statement are not affected by any of its substatements. Each
282          * of the substatements is free to make its own policy.
283          *
284          * <p>
285          * This policy is typically used by static constant statements such as {@code description} or {@code length},
286          * where the baseline RFC7950 does not allow any impact. A {@code description} could hold an extension statement
287          * in which case this interaction would come into play. Normal YANG will see empty substatements, so the reactor
288          * will be free to complete reuse the context.
289          *
290          * <p>
291          * In case any substatement is of stronger policy, it is up to the reactor to handle correct handling of
292          * resulting subobjects.
293          */
294         // TODO: does this mean source must have transitioned to ModelProcessingPhase.EFFECTIVE_MODEL?
295         CONTEXT_INDEPENDENT,
296         /**
297          * Create a copy sharing declared instance, but otherwise having a separate disconnected lifecycle.
298          */
299         // TODO: will the copy transition to ModelProcessingPhase.FULL_DECLARATION or which phase?
300         DECLARED_COPY,
301         /**
302          * Reject any attempt to copy this statement. This is useful for statements that are defined as top-level
303          * constructs, such as {@code contact}, {@code deviation} and similar.
304          */
305         REJECT,
306         /**
307          * Ignore this statement's existence for the purposes of the new place -- it is not impacted. This guidance
308          * is left here for completeness, as it can have justifiable uses (but I can't think of any). Any substatements
309          * need to be ignored, too.
310          */
311         IGNORE;
312     }
313 }