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