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