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