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