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