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