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