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