Fix javadoc to comply with JDK14
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / schema / stream / NormalizedNodeStreamWriter.java
1 /*
2  * Copyright (c) 2014 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.data.api.schema.stream;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import java.io.Closeable;
14 import java.io.Flushable;
15 import java.io.IOException;
16 import javax.xml.transform.dom.DOMSource;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.concepts.ExtensibleObject;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24
25 /**
26  * Event Stream Writer based on Normalized Node tree representation.
27  *
28  * <h2>Writing Event Stream</h2>
29  * Each entity is emitted by invoking its corresponding {@code start*} event, optionally followed by interior events and
30  * invoking {@link #endNode()}. Some entities supported nested entities, some do not, see below for restrictions.
31  *
32  * <p>
33  * While this interface defines basic events, the event stream may be extended through
34  * {@link NormalizedNodeStreamWriterExtension}s discoverable through {@link #getExtensions()} method. The set of these
35  * extensions is immutable during the lifetime of a writer and may be freely cached.
36  *
37  * <ul>
38  * <li>{@code container} - Container node representation, start event is emitted using
39  * {@link #startContainerNode(NodeIdentifier, int)}.
40  * </li>
41  *
42  * <li>{@code list} - YANG list statement has two representation in event stream - unkeyed list and map. An unkeyed
43  * list is YANG list which did not specify a {@code key} statement. A map is a {@code list} with a {@code key}
44  * statement.
45  * <ul>
46  * <li>{@code Map} - Map start event is emitted using {@link #startMapNode(NodeIdentifier, int)}. Each map entry start
47  * is emitted using {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
48  * </li>
49  * <li>{@code UnkeyedList} - Unkeyed list represent list without keys, unkeyed list start is emitted using
50  * {@link #startUnkeyedList(NodeIdentifier, int)}. Each list item is emitted using
51  * {@link #startUnkeyedListItem(NodeIdentifier, int)}.</li>
52  * </ul>
53  * </li>
54  *
55  * <li>{@code leaf} - Leaf node start event is emitted using {@link #startLeafNode(NodeIdentifier)}. Leaf node values
56  * need to be emitted through {@link #scalarValue(Object)}.
57  * </li>
58  *
59  * <li>{@code leaf-list} - Leaf list start is emitted using {@link #startLeafSet(NodeIdentifier, int)}. Individual
60  * leaf-list entries are emitted using {@link #startLeafSetEntryNode(NodeWithValue)}.
61  *
62  * <li>{@code anyxml} - An anyxml node event is emitted using {@link #startAnyxmlNode(NodeIdentifier, Class)}.</li>
63  *
64  * <li>{@code choice} - Choice node event is emitted by {@link #startChoiceNode(NodeIdentifier, int)} event.</li>
65  *
66  * <li>{@code augment} - Represents augmentation, augmentation node is started by invoking
67  * {@link #startAugmentationNode(AugmentationIdentifier)}.
68  * </li>
69  * </ul>
70  *
71  * <h3>Implementation notes</h3>
72  *
73  * <p>
74  * Implementations of this interface must not hold user suppled objects and resources needlessly.
75  */
76 public interface NormalizedNodeStreamWriter extends Closeable, Flushable,
77         ExtensibleObject<NormalizedNodeStreamWriter, NormalizedNodeStreamWriterExtension> {
78     /**
79      * Methods in this interface allow users to hint the underlying implementation about the sizing of container-like
80      * constructors (leafLists, containers, etc.). These hints may be taken into account by a particular implementation
81      * to improve performance, but clients are not required to provide hints. This constant should be used by clients
82      * who either do not have the sizing information, or do not wish to divulge it (for whatever reasons).
83      *
84      * <p>
85      * Implementations are free to ignore these hints completely, but if they do use them, they are expected to be
86      * resilient in face of missing and mismatched hints, which is to say the user can specify startLeafSet(..., 1) and
87      * then call leafNode() 15 times.
88      *
89      * <p>
90      * The acceptable hint values are non-negative integers and this constant, all other values will result, based on
91      * implementation preference, in the hint being completely ignored or IllegalArgumentException being thrown.
92      */
93     int UNKNOWN_SIZE = -1;
94
95     /**
96      * Emits a start of leaf node event.
97      *
98      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
99      * @throws NullPointerException if {@code name} is null
100      * @throws IllegalArgumentException If emitted leaf node was emitted multiple times.
101      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
102      *                               node.
103      * @throws IOException if an underlying IO error occurs
104      */
105     void startLeafNode(NodeIdentifier name) throws IOException;
106
107     /**
108      * Emits a start of system-ordered leaf set (leaf-list). While this entity is open,
109      * only {@link #startLeafSetEntryNode(NodeWithValue)} calls are valid. Implementations are free to reorder entries
110      * within the leaf-list.
111      *
112      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
113      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
114      *                      unknown. This is only hint and should not fail writing of child events, if there are more
115      *                      events than count.
116      * @throws NullPointerException if {@code name} is null
117      * @throws IllegalArgumentException If emitted leaf node is invalid in current context or was emitted multiple
118      *                                  times.
119      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
120      *                               node.
121      * @throws IOException if an underlying IO error occurs
122      */
123     void startLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
124
125     /**
126      * Emits a start of a user-ordered leaf set (leaf-list). While this entity is open, only
127      * {@link #startLeafSetEntryNode(NodeWithValue)} calls are valid. Implementations must retain the same entry order.
128      *
129      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
130      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
131      *                      unknown. This is only hint and should not fail writing of child events, if there are more
132      *                      events than count.
133      * @throws NullPointerException if {@code name} is null
134      * @throws IllegalArgumentException If emitted leaf node is invalid in current context or was emitted multiple
135      *                                  times.
136      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
137      *                               node.
138      * @throws IOException if an underlying IO error occurs
139      */
140     void startOrderedLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
141
142     /**
143      * Emits a leaf set entry node.
144      *
145      * @param name name of the node as defined in the schema.
146      * @throws NullPointerException if {@code name} is null
147      * @throws IllegalArgumentException if {@code name} does not match enclosing leaf set entity
148      * @throws IllegalStateException If node was emitted outside {@code leaf set} node.
149      * @throws IOException if an underlying IO error occurs
150      */
151     void startLeafSetEntryNode(NodeWithValue<?> name) throws IOException;
152
153     /**
154      * Emits start of new container. Valid sub-events are:
155      * <ul>
156      * <li>{@link #startLeafNode}</li>
157      * <li>{@link #startAnyxmlNode(NodeIdentifier, Class)}</li>
158      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
159      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
160      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
161      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
162      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
163      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
164      * </ul>
165      *
166      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
167      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
168      *                      unknown. This is only hint and should not fail writing of child events, if there are more
169      *                      events than count.
170      * @throws NullPointerException if {@code name} is null
171      * @throws IllegalArgumentException  If emitted node is invalid in current context or was emitted multiple times.
172      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
173      *                               node.
174      * @throws IOException if an underlying IO error occurs
175      */
176     void startContainerNode(NodeIdentifier name, int childSizeHint) throws IOException;
177
178     /**
179      * Emits start of unkeyed list node event. Valid subevents is only
180      * {@link #startUnkeyedListItem(NodeIdentifier, int)}.
181      *
182      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
183      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
184      *                      unknown. This is only hint and should not fail writing of child events, if there are more
185      *                      events than count.
186      * @throws NullPointerException if {@code name} is null
187      * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
188      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
189      *                               node.
190      * @throws IOException if an underlying IO error occurs
191      */
192     void startUnkeyedList(NodeIdentifier name, int childSizeHint) throws IOException;
193
194     /**
195      * Emits start of new unkeyed list item. Valid sub-events are:
196      * <ul>
197      * <li>{@link #startLeafNode}</li>
198      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
199      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
200      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
201      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
202      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
203      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
204      * </ul>
205      *
206      * @param name Identifier of node
207      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
208      *                      unknown. This is only hint and should not fail writing of child events, if there are more
209      *                      events than count.
210      * @throws NullPointerException if {@code name} is null
211      * @throws IllegalStateException If node was emitted outside <code>unkeyed list</code> node.
212      * @throws IOException if an underlying IO error occurs
213      */
214     void startUnkeyedListItem(NodeIdentifier name, int childSizeHint) throws IOException;
215
216     /**
217      * Emits start of map node event. Valid subevent is only
218      * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
219      *
220      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
221      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
222      *                      unknown. This is only hint and should not fail writing of child events, if there are more
223      *                      events than count.
224      * @throws NullPointerException if {@code name} is null
225      * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
226      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
227      *                               node.
228      * @throws IOException if an underlying IO error occurs
229      */
230     void startMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
231
232     /**
233      * Emits start of map entry. Valid sub-events are:
234      * <ul>
235      * <li>{@link #startLeafNode}</li>
236      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
237      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
238      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
239      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
240      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
241      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
242      * </ul>
243      *
244      * @param identifier QName to value pairs of keys of map entry node.
245      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
246      *                      unknown. This is only hint and should not fail writing of child events, if there are more
247      *                      events than count.
248      * @throws NullPointerException if {@code name} is null
249      * @throws IllegalArgumentException If key contains incorrect value.
250      * @throws IllegalStateException If node was emitted outside {@code map entry} node.
251      * @throws IOException if an underlying IO error occurs
252      */
253     void startMapEntryNode(NodeIdentifierWithPredicates identifier, int childSizeHint) throws IOException;
254
255     /**
256      * Emits start of map node event.  Valid subevent is only
257      * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
258      *
259      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
260      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
261      *                      unknown. This is only hint and should not fail writing of child events, if there are more
262      *                      events than count.
263      * @throws NullPointerException if {@code name} is null
264      * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
265      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
266      *                               node.
267      * @throws IOException if an underlying IO error occurs
268      */
269     void startOrderedMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
270
271     /**
272      * Emits start of a choice node event.
273      *
274      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
275      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
276      *                      unknown. This is only hint and should not fail writing of child events, if there are more
277      *                      events than count.
278      * @throws NullPointerException if {@code name} is null
279      * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
280      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
281      *                               node.
282      * @throws IOException if an underlying IO error occurs
283      */
284     void startChoiceNode(NodeIdentifier name, int childSizeHint) throws IOException;
285
286     /**
287      * Emits start of augmentation node. Valid sub-events are:
288      * <ul>
289      * <li>{@link #startLeafNode}</li>
290      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
291      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
292      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
293      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
294      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
295      * </ul>
296      *
297      * @param identifier Augmentation identifier
298      * @throws NullPointerException if {@code identifier} is null
299      * @throws IllegalArgumentException If augmentation is invalid in current context.
300      * @throws IOException if an underlying IO error occurs
301      */
302     void startAugmentationNode(AugmentationIdentifier identifier) throws IOException;
303
304     /**
305      * Start emitting a new anydata node identified by name.
306      *
307      * @param name The name of the anydata element
308      * @param objectModel The object model of anydata content
309      * @return True if the specified object model is supported by this extension and the process of emitting the node
310      *         has started. False if the object model is not supported and the node has not started to be emitted.
311      * @throws NullPointerException if any argument is null
312      * @throws IOException if an underlying IO error occurs
313      */
314     @Beta
315     boolean startAnydataNode(NodeIdentifier name, Class<?> objectModel) throws IOException;
316
317     /**
318      * Emits a start of anyxml node event.
319      *
320      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
321      * @param objectModel The object model of anyxml content
322      * @return True if the specified object model is supported by this extension and the process of emitting the node
323      *         has started. False if the object model is not supported and the node has not started to be emitted.
324      * @throws NullPointerException if any argument is null
325      * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
326      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
327      *                               node.
328      * @throws IOException if an underlying IO error occurs
329      */
330     boolean startAnyxmlNode(NodeIdentifier name, Class<?> objectModel) throws IOException;
331
332     /**
333      * Set the value of current anyxml node. This call is only valid within the context in which an anyxml node is open.
334      *
335      * @param value node value
336      * @throws NullPointerException if the argument is null
337      * @throws IllegalArgumentException if the argument does not represents a valid value
338      * @throws IllegalStateException if an anyxml node is not open or if it's value has already been set and this
339      *                               implementation does not allow resetting the value.
340      * @throws IOException if an underlying IO error occurs
341      */
342     // FIXME: 6.0.0: this probably should integrated with scalarValue()
343     void domSourceValue(DOMSource value) throws IOException;
344
345     /**
346      * Emits start of new YANG-modeled anyxml node. Valid sub-events are:
347      * <ul>
348      * <li>{@link #startLeafNode}</li>
349      * <li>{@link #startContainerNode}</li>
350      * <li>{@link #startLeafSet}</li>
351      * <li>{@link #startMapNode}</li>
352      * <li>{@link #startUnkeyedList}</li>
353      * </ul>
354      *
355      * @param name name of node as defined in schema, namespace and revision are derived from parent node.
356      * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
357      *                      unknown. This is only hint and should not fail writing of child events, if there are more
358      *                      events than count.
359      * @throws NullPointerException if {@code name} is null
360      * @throws IllegalArgumentException  If emitted node is invalid in current context or was emitted multiple times.
361      * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
362      *                               node.
363      * @throws IOException if an underlying IO error occurs
364      */
365     void startYangModeledAnyXmlNode(NodeIdentifier name, int childSizeHint) throws IOException;
366
367     /**
368      * Emits end event for node.
369      *
370      * @throws IllegalStateException If there is no start* event to be closed.
371      * @throws IOException if an underlying IO error occurs
372      */
373     void endNode() throws IOException;
374
375     /**
376      * Attach the specified {@link DataSchemaNode} to the next node which will get started or emitted. The default
377      * implementation does nothing.
378      *
379      * @param schema DataSchemaNode
380      * @throws NullPointerException if the argument is null
381      */
382     default void nextDataSchemaNode(final @NonNull DataSchemaNode schema) {
383         requireNonNull(schema);
384     }
385
386     /**
387      * Set the value of current node. This call is only valid within the context in which a value-bearing node is open,
388      * such as a LeafNode, LeafSetEntryNode.
389      *
390      * @param value node value, must be effectively immutable
391      * @throws NullPointerException if the argument is null
392      * @throws IllegalArgumentException if the argument does not represents a valid value
393      * @throws IllegalStateException if a value-bearing node is not open or if it's value has already been set and this
394      *                               implementation does not allow resetting the value.
395      * @throws IOException if an underlying IO error occurs
396      */
397     void scalarValue(@NonNull Object value) throws IOException;
398
399     @Override
400     void close() throws IOException;
401
402     @Override
403     void flush() throws IOException;
404 }