1b1bd097b1988527355cd14dcb1e80ccf3e20682
[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 com.google.common.base.Preconditions;
11 import java.io.Closeable;
12 import java.io.Flushable;
13 import java.io.IOException;
14 import javax.annotation.Nonnull;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
19 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
20
21
22 /**
23  * Event Stream Writer based on Normalized Node tree representation
24  *
25  * <h3>Writing Event Stream</h3>
26  *
27  * <ul>
28  * <li><code>container</code> - Container node representation, start event is
29  * emitted using {@link #startContainerNode(NodeIdentifier, int)} and node end event is
30  * emitted using {@link #endNode()}. Container node is implementing
31  * the org.opendaylight.yangtools.yang.binding.DataObject interface.
32  *
33  * <li><code>list</code> - YANG list statement has two representation in event
34  * stream - unkeyed list and map. Unkeyed list is YANG list which did not
35  * specify key.
36  *
37  * <ul>
38  * <li><code>Map</code> - Map start event is emitted using
39  * {@link #startMapNode(NodeIdentifier, int)} and is ended using {@link #endNode()}. Each map
40  * entry start is emitted using {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)} with Map of keys
41  * and finished using {@link #endNode()}.</li>
42  *
43  * <li><code>UnkeyedList</code> - Unkeyed list represent list without keys,
44  * unkeyed list start is emitted using {@link #startUnkeyedList(NodeIdentifier, int)} list
45  * end is emitted using {@link #endNode()}. Each list item is emitted using
46  * {@link #startUnkeyedListItem(NodeIdentifier, int)} and ended using {@link #endNode()}.</li>
47  * </ul></li>
48  *
49  * <li><code>leaf</code> - Leaf node event is emitted using
50  * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted for
51  * leaf node.</li>
52  *
53  * <li><code>leaf-list</code> - Leaf list start is emitted using
54  * {@link #startLeafSet(NodeIdentifier, int)}. Leaf list end is emitted using
55  * {@link #endNode()}. Leaf list entries are emmited using
56  * {@link #leafSetEntryNode(QName, Object)}.
57  *
58  * <li><code>anyxml - AN node event is emitted using
59  * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted
60  * for anyxml node.</code></li>
61  *
62  *
63  * <li><code>choice</code> Choice node event is emmited by
64  * {@link #startChoiceNode(NodeIdentifier, int)} event and
65  * finished by invoking {@link #endNode()}
66  * <li>
67  * <code>augment</code> - Represents augmentation, augmentation node is started
68  * by invoking {@link #startAugmentationNode(AugmentationIdentifier)} and
69  * finished by invoking {@link #endNode()}.</li>
70  *
71  * </ul>
72  *
73  * <h3>Implementation notes</h3>
74  *
75  * <p>
76  * Implementations of this interface must not hold user suppled objects
77  * and resources needlessly.
78  *
79  */
80 public interface NormalizedNodeStreamWriter extends Closeable, Flushable, DataSchemaNodeAware {
81
82     /**
83      * Methods in this interface allow users to hint the underlying
84      * implementation about the sizing of container-like constructors
85      * (leafLists, containers, etc.). These hints may be taken into account by a
86      * particular implementation to improve performance, but clients are not
87      * required to provide hints. This constant should be used by clients who
88      * either do not have the sizing information, or do not wish to divulge it
89      * (for whatever reasons). Implementations are free to ignore these hints
90      * completely, but if they do use them, they are expected to be resilient in
91      * face of missing and mismatched hints, which is to say the user can
92      * specify startLeafSet(..., 1) and then call leafNode() 15 times.
93      * <p>
94      * The acceptable hint values are non-negative integers and this constant,
95      * all other values will result, based on implementation preference, in the
96      * hint being completely ignored or IllegalArgumentException being thrown.
97      */
98     int UNKNOWN_SIZE = -1;
99
100     /**
101      *
102      * Emits a leaf node event with supplied value.
103      *
104      * @param name
105      *            name of node as defined in schema, namespace and revision are
106      *            derived from parent node.
107      * @param value
108      *            Value of leaf node. v
109      * @throws IllegalArgumentException
110      *             If emitted leaf node has invalid value in current context or
111      *             was emitted multiple times.
112      * @throws IllegalStateException
113      *             If node was emitted inside <code>map</code>,
114      *             <code>choice</code> <code>unkeyed list</code> node.
115      * @throws IOException if an underlying IO error occurs
116      */
117     void leafNode(NodeIdentifier name, Object value) throws IOException;
118
119     /**
120      *
121      * Emits a start of leaf set (leaf-list).
122      * <p>
123      * Emits start of leaf set, during writing leaf set event, only
124      * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
125      * finished by calling {@link #endNode()}.
126      *
127      * @param name
128      *            name of node as defined in schema, namespace and revision are
129      *            derived from parent node.
130      * @param childSizeHint
131      *            Non-negative count of expected direct child nodes or
132      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
133      *            and should not fail writing of child events, if there are more
134      *            events than count.
135      * @throws IllegalArgumentException
136      *             If emitted leaf node is invalid in current context or was
137      *             emitted multiple times.
138      * @throws IllegalStateException
139      *             If node was emitted inside <code>map</code>,
140      *             <code>choice</code> <code>unkeyed list</code> node.
141      * @throws IOException if an underlying IO error occurs
142      */
143     void startLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
144
145     /**
146      *
147      * Emits a start of leaf set (leaf-list).
148      * <p>
149      * Emits start of leaf set, during writing leaf set event, only
150      * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
151      * finished by calling {@link #endNode()}.
152      *
153      * @param name
154      *            name of node as defined in schema, namespace and revision are
155      *            derived from parent node.
156      * @param childSizeHint
157      *            Non-negative count of expected direct child nodes or
158      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
159      *            and should not fail writing of child events, if there are more
160      *            events than count.
161      * @throws IllegalArgumentException
162      *             If emitted leaf node is invalid in current context or was
163      *             emitted multiple times.
164      * @throws IllegalStateException
165      *             If node was emitted inside <code>map</code>,
166      *             <code>choice</code> <code>unkeyed list</code> node.
167      * @throws IOException if an underlying IO error occurs
168      */
169     void startOrderedLeafSet(NodeIdentifier name, int childSizeHint) throws IOException, IllegalArgumentException;
170
171     /**
172      * Emits a leaf set entry node
173      *
174      * @param name
175      *            name of the node as defined in the schema.
176      * @param value
177      *            Value of leaf set entry node. Supplied object MUST BE constant over time.
178      * @throws IllegalArgumentException
179      *             If emitted leaf node has invalid value.
180      * @throws IllegalStateException
181      *             If node was emitted outside <code>leaf set</code> node.
182      * @throws IOException if an underlying IO error occurs
183      */
184     void leafSetEntryNode(QName name, Object value) throws IOException;
185
186     /**
187      *
188      * Emits start of new container.
189      *
190      * <p>
191      * End of container event is emitted by invoking {@link #endNode()}.
192      *
193      * <p>
194      * Valid sub-events are:
195      * <ul>
196      * <li>{@link #leafNode}</li>
197      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
198      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
199      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
200      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
201      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
202      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
203      * </ul>
204      *
205      * @param name
206      *            name of node as defined in schema, namespace and revision are
207      *            derived from parent node.
208      * @param childSizeHint
209      *            Non-negative count of expected direct child nodes or
210      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
211      *            and should not fail writing of child events, if there are more
212      *            events than count.
213      * @throws IllegalArgumentException
214      *             If emitted node is invalid in current context or was emitted
215      *             multiple times.
216      * @throws IllegalStateException
217      *             If node was emitted inside <code>map</code>,
218      *             <code>choice</code> <code>unkeyed list</code> node.
219      * @throws IOException if an underlying IO error occurs
220      */
221     void startContainerNode(NodeIdentifier name, int childSizeHint) throws IOException;
222
223     /**
224      *
225      * Emits start of unkeyed list node event.
226      *
227      * <p>
228      * End of unkeyed list event is emitted by invoking {@link #endNode()}.
229      * Valid subevents is only {@link #startUnkeyedListItem(NodeIdentifier, int)}. All other
230      * methods will throw {@link IllegalArgumentException}.
231      *
232      * @param name
233      *            name of node as defined in schema, namespace and revision are
234      *            derived from parent node.
235      * @param childSizeHint
236      *            Non-negative count of expected direct child nodes or
237      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
238      *            and should not fail writing of child events, if there are more
239      *            events than count.
240      * @throws IllegalArgumentException
241      *             If emitted node is invalid in current context or was emitted
242      *             multiple times.
243      * @throws IllegalStateException
244      *             If node was emitted inside <code>map</code>,
245      *             <code>choice</code> <code>unkeyed list</code> node.
246      * @throws IOException if an underlying IO error occurs
247      */
248     void startUnkeyedList(NodeIdentifier name, int childSizeHint) throws IOException;
249
250     /**
251      * Emits start of new unkeyed list item.
252      *
253      * <p>
254      * Unkeyed list item event is finished by invoking {@link #endNode()}. Valid
255      * sub-events are:
256      * <ul>
257      * <li>{@link #leafNode}</li>
258      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
259      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
260      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
261      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
262      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
263      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
264      * </ul>
265      *
266      * @param name Identifier of node
267      * @param childSizeHint
268      *            Non-negative count of expected direct child nodes or
269      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
270      *            and should not fail writing of child events, if there are more
271      *            events than count.
272      * @throws IllegalStateException
273      *             If node was emitted outside <code>unkeyed list</code> node.
274      * @throws IOException if an underlying IO error occurs
275      */
276     void startUnkeyedListItem(NodeIdentifier name, int childSizeHint) throws IOException;
277
278     /**
279      *
280      * Emits start of map node event.
281      *
282      * <p>
283      * End of map node event is emitted by invoking {@link #endNode()}. Valid
284      * subevents is only
285      * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
286      * methods will throw {@link IllegalArgumentException}.
287      *
288      * @param name
289      *            name of node as defined in schema, namespace and revision are
290      *            derived from parent node.
291      * @param childSizeHint
292      *            Non-negative count of expected direct child nodes or
293      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
294      *            and should not fail writing of child events, if there are more
295      *            events than count.
296      * @throws IllegalArgumentException
297      *             If emitted node is invalid in current context or was emitted
298      *             multiple times.
299      * @throws IllegalStateException
300      *             If node was emitted inside <code>map</code>,
301      *             <code>choice</code> <code>unkeyed list</code> node.
302      * @throws IOException if an underlying IO error occurs
303      */
304     void startMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
305
306     /**
307      *
308      * Emits start of map entry.
309      *
310      * <p>
311      * End of map entry event is emitted by invoking {@link #endNode()}.
312      *
313      * <p>
314      * Valid sub-events are:
315      * <ul>
316      * <li>{@link #leafNode}</li>
317      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
318      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
319      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
320      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
321      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
322      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
323      * </ul>
324      *
325      *
326      * @param identifier
327      *            QName to value pairs of keys of map entry node. Values  MUST BE constant over time.
328      * @param childSizeHint
329      *            Non-negative count of expected direct child nodes or
330      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
331      *            and should not fail writing of child events, if there are more
332      *            events than count.
333      * @throws IllegalArgumentException
334      *             If key contains incorrect value.
335      * @throws IllegalStateException
336      *             If node was emitted outside <code>map entry</code> node.
337      * @throws IOException if an underlying IO error occurs
338      */
339     void startMapEntryNode(NodeIdentifierWithPredicates identifier, int childSizeHint) throws IOException;
340
341     /**
342      *
343      * Emits start of map node event.
344      *
345      * <p>
346      * End of map node event is emitted by invoking {@link #endNode()}. Valid
347      * subevents is only
348      * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
349      * methods will throw {@link IllegalArgumentException}.
350      *
351      * @param name
352      *            name of node as defined in schema, namespace and revision are
353      *            derived from parent node.
354      * @param childSizeHint
355      *            Non-negative count of expected direct child nodes or
356      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
357      *            and should not fail writing of child events, if there are more
358      *            events than count.
359      * @throws IllegalArgumentException
360      *             If emitted node is invalid in current context or was emitted
361      *             multiple times.
362      * @throws IllegalStateException
363      *             If node was emitted inside <code>map</code>,
364      *             <code>choice</code> <code>unkeyed list</code> node.
365      * @throws IOException if an underlying IO error occurs
366      */
367     void startOrderedMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
368
369     /**
370      *
371      *
372      *
373      * @param name
374      *            name of node as defined in schema, namespace and revision are
375      *            derived from parent node.
376      * @param childSizeHint
377      *            Non-negative count of expected direct child nodes or
378      *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
379      *            and should not fail writing of child events, if there are more
380      *            events than count.
381      * @throws IllegalArgumentException
382      *             If emitted node is invalid in current context or was emitted
383      *             multiple times.
384      * @throws IllegalStateException
385      *             If node was emitted inside <code>map</code>,
386      *             <code>choice</code> <code>unkeyed list</code> node.
387      * @throws IOException if an underlying IO error occurs
388      */
389     void startChoiceNode(NodeIdentifier name, int childSizeHint) throws IOException;
390
391     /**
392      * Emits start of augmentation node.
393      *
394      * <p>
395      * End of augmentation event is emitted by invoking {@link #endNode()}.
396      *
397      * <p>
398      * Valid sub-events are:
399      *
400      * <ul>
401      * <li>{@link #leafNode}</li>
402      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
403      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
404      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
405      * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
406      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
407      * </ul>
408      *
409      * @param identifier
410      *            Augmentation identifier
411      * @throws IllegalArgumentException
412      *             If augmentation is invalid in current context.
413      * @throws IOException if an underlying IO error occurs
414      */
415     void startAugmentationNode(AugmentationIdentifier identifier) throws IOException;
416
417     /**
418      * Emits anyxml node event.
419      *
420      * @param name
421      *            name of node as defined in schema, namespace and revision are
422      *            derived from parent node.
423      * @param value
424      *             Value of AnyXml node.
425      * @throws IllegalArgumentException
426      *             If emitted node is invalid in current context or was emitted
427      *             multiple times.
428      * @throws IllegalStateException
429      *             If node was emitted inside <code>map</code>,
430      *             <code>choice</code> <code>unkeyed list</code> node.
431      * @throws IOException if an underlying IO error occurs
432      */
433     void anyxmlNode(NodeIdentifier name, Object value) throws IOException;
434
435     /**
436     *
437     * Emits start of new yang modeled anyXml node.
438     *
439     * <p>
440     * End of yang modeled anyXml node event is emitted by invoking {@link #endNode()}.
441     *
442     * <p>
443     * Valid sub-events are:
444     * <ul>
445     * <li>{@link #leafNode}</li>
446     * <li>{@link #startContainerNode}</li>
447     * <li>{@link #startLeafSet}</li>
448     * <li>{@link #startMapNode}</li>
449     * <li>{@link #startUnkeyedList}</li>
450     * </ul>
451     *
452     * @param name
453     *            name of node as defined in schema, namespace and revision are
454     *            derived from parent node.
455     * @param childSizeHint
456     *            Non-negative count of expected direct child nodes or
457     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
458     *            and should not fail writing of child events, if there are more
459     *            events than count.
460     * @throws IllegalArgumentException
461     *             If emitted node is invalid in current context or was emitted
462     *             multiple times.
463     * @throws IllegalStateException
464     *             If node was emitted inside <code>map</code>,
465     *             <code>choice</code> <code>unkeyed list</code> node.
466     * @throws IOException if an underlying IO error occurs
467     */
468     void startYangModeledAnyXmlNode(NodeIdentifier name, int childSizeHint) throws IOException;
469
470     /**
471      * Emits end event for node.
472      *
473      * @throws IllegalStateException If there is no start* event to be closed.
474      * @throws IOException if an underlying IO error occurs
475      */
476     void endNode() throws IOException;
477
478     /**
479      * Attach the specified {@link DataSchemaNode} to the next node which will get started or emitted. The default
480      * implementation does nothing.
481      *
482      * @param schema DataSchemaNode
483      * @throws NullPointerException if the argument is null
484      */
485     @Override
486     default void nextDataSchemaNode(@Nonnull final DataSchemaNode schema) {
487         Preconditions.checkNotNull(schema);
488     }
489
490     @Override
491     void close() throws IOException;
492
493     @Override
494     void flush() throws IOException;
495 }