2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.api.schema.stream;
10 import com.google.common.base.Preconditions;
11 import java.io.Closeable;
12 import java.io.Flushable;
13 import java.io.IOException;
14 import javax.annotation.Nonnull;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
19 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
23 * Event Stream Writer based on Normalized Node tree representation
25 * <h3>Writing Event Stream</h3>
28 * <li><code>container</code> - Container node representation, start event is
29 * emitted using {@link #startContainerNode(NodeIdentifier, int)} and node end event is
30 * emitted using {@link #endNode()}. Container node is implementing
31 * the org.opendaylight.yangtools.yang.binding.DataObject interface.
33 * <li><code>list</code> - YANG list statement has two representation in event
34 * stream - unkeyed list and map. Unkeyed list is YANG list which did not
38 * <li><code>Map</code> - Map start event is emitted using
39 * {@link #startMapNode(NodeIdentifier, int)} and is ended using {@link #endNode()}. Each map
40 * entry start is emitted using {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)} with Map of keys
41 * and finished using {@link #endNode()}.</li>
43 * <li><code>UnkeyedList</code> - Unkeyed list represent list without keys,
44 * unkeyed list start is emitted using {@link #startUnkeyedList(NodeIdentifier, int)} list
45 * end is emitted using {@link #endNode()}. Each list item is emitted using
46 * {@link #startUnkeyedListItem(NodeIdentifier, int)} and ended using {@link #endNode()}.</li>
49 * <li><code>leaf</code> - Leaf node event is emitted using
50 * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted for
53 * <li><code>leaf-list</code> - Leaf list start is emitted using
54 * {@link #startLeafSet(NodeIdentifier, int)}. Leaf list end is emitted using
55 * {@link #endNode()}. Leaf list entries are emmited using
56 * {@link #leafSetEntryNode(QName, Object)}.
58 * <li><code>anyxml - AN node event is emitted using
59 * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted
60 * for anyxml node.</code></li>
63 * <li><code>choice</code> Choice node event is emmited by
64 * {@link #startChoiceNode(NodeIdentifier, int)} event and
65 * finished by invoking {@link #endNode()}
67 * <code>augment</code> - Represents augmentation, augmentation node is started
68 * by invoking {@link #startAugmentationNode(AugmentationIdentifier)} and
69 * finished by invoking {@link #endNode()}.</li>
73 * <h3>Implementation notes</h3>
76 * Implementations of this interface must not hold user suppled objects
77 * and resources needlessly.
80 public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
83 * Methods in this interface allow users to hint the underlying
84 * implementation about the sizing of container-like constructors
85 * (leafLists, containers, etc.). These hints may be taken into account by a
86 * particular implementation to improve performance, but clients are not
87 * required to provide hints. This constant should be used by clients who
88 * either do not have the sizing information, or do not wish to divulge it
89 * (for whatever reasons). Implementations are free to ignore these hints
90 * completely, but if they do use them, they are expected to be resilient in
91 * face of missing and mismatched hints, which is to say the user can
92 * specify startLeafSet(..., 1) and then call leafNode() 15 times.
95 * The acceptable hint values are non-negative integers and this constant,
96 * all other values will result, based on implementation preference, in the
97 * hint being completely ignored or IllegalArgumentException being thrown.
99 int UNKNOWN_SIZE = -1;
102 * Emits a leaf node event with supplied value.
105 * name of node as defined in schema, namespace and revision are
106 * derived from parent node.
108 * Value of leaf node. v
109 * @throws IllegalArgumentException
110 * If emitted leaf node has invalid value in current context or
111 * was emitted multiple times.
112 * @throws IllegalStateException
113 * If node was emitted inside <code>map</code>,
114 * <code>choice</code> <code>unkeyed list</code> node.
115 * @throws IOException if an underlying IO error occurs
117 void leafNode(NodeIdentifier name, Object value) throws IOException;
120 * Emits a start of leaf set (leaf-list).
123 * Emits start of leaf set, during writing leaf set event, only
124 * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
125 * finished by calling {@link #endNode()}.
128 * name of node as defined in schema, namespace and revision are
129 * derived from parent node.
130 * @param childSizeHint
131 * Non-negative count of expected direct child nodes or
132 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
133 * and should not fail writing of child events, if there are more
135 * @throws IllegalArgumentException
136 * If emitted leaf node is invalid in current context or was
137 * emitted multiple times.
138 * @throws IllegalStateException
139 * If node was emitted inside <code>map</code>,
140 * <code>choice</code> <code>unkeyed list</code> node.
141 * @throws IOException if an underlying IO error occurs
143 void startLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
146 * Emits a start of leaf set (leaf-list).
149 * Emits start of leaf set, during writing leaf set event, only
150 * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
151 * finished by calling {@link #endNode()}.
154 * name of node as defined in schema, namespace and revision are
155 * derived from parent node.
156 * @param childSizeHint
157 * Non-negative count of expected direct child nodes or
158 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
159 * and should not fail writing of child events, if there are more
161 * @throws IllegalArgumentException
162 * If emitted leaf node is invalid in current context or was
163 * emitted multiple times.
164 * @throws IllegalStateException
165 * If node was emitted inside <code>map</code>,
166 * <code>choice</code> <code>unkeyed list</code> node.
167 * @throws IOException if an underlying IO error occurs
169 void startOrderedLeafSet(NodeIdentifier name, int childSizeHint) throws IOException, IllegalArgumentException;
172 * Emits a leaf set entry node.
175 * name of the node as defined in the schema.
177 * Value of leaf set entry node. Supplied object MUST BE constant over time.
178 * @throws IllegalArgumentException
179 * If emitted leaf node has invalid value.
180 * @throws IllegalStateException
181 * If node was emitted outside <code>leaf set</code> node.
182 * @throws IOException if an underlying IO error occurs
184 void leafSetEntryNode(QName name, Object value) throws IOException;
187 * Emits start of new container.
190 * End of container event is emitted by invoking {@link #endNode()}.
193 * Valid sub-events are:
195 * <li>{@link #leafNode}</li>
196 * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
197 * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
198 * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
199 * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
200 * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
201 * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
205 * name of node as defined in schema, namespace and revision are
206 * derived from parent node.
207 * @param childSizeHint
208 * Non-negative count of expected direct child nodes or
209 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
210 * and should not fail writing of child events, if there are more
212 * @throws IllegalArgumentException
213 * If emitted node is invalid in current context or was emitted
215 * @throws IllegalStateException
216 * If node was emitted inside <code>map</code>,
217 * <code>choice</code> <code>unkeyed list</code> node.
218 * @throws IOException if an underlying IO error occurs
220 void startContainerNode(NodeIdentifier name, int childSizeHint) throws IOException;
223 * Emits start of unkeyed list node event.
226 * End of unkeyed list event is emitted by invoking {@link #endNode()}.
227 * Valid subevents is only {@link #startUnkeyedListItem(NodeIdentifier, int)}. All other
228 * methods will throw {@link IllegalArgumentException}.
231 * name of node as defined in schema, namespace and revision are
232 * derived from parent node.
233 * @param childSizeHint
234 * Non-negative count of expected direct child nodes or
235 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
236 * and should not fail writing of child events, if there are more
238 * @throws IllegalArgumentException
239 * If emitted node is invalid in current context or was emitted
241 * @throws IllegalStateException
242 * If node was emitted inside <code>map</code>,
243 * <code>choice</code> <code>unkeyed list</code> node.
244 * @throws IOException if an underlying IO error occurs
246 void startUnkeyedList(NodeIdentifier name, int childSizeHint) throws IOException;
249 * Emits start of new unkeyed list item.
252 * Unkeyed list item event is finished by invoking {@link #endNode()}. Valid
255 * <li>{@link #leafNode}</li>
256 * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
257 * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
258 * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
259 * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
260 * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
261 * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
264 * @param name Identifier of node
265 * @param childSizeHint
266 * Non-negative count of expected direct child nodes or
267 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
268 * and should not fail writing of child events, if there are more
270 * @throws IllegalStateException
271 * If node was emitted outside <code>unkeyed list</code> node.
272 * @throws IOException if an underlying IO error occurs
274 void startUnkeyedListItem(NodeIdentifier name, int childSizeHint) throws IOException;
277 * Emits start of map node event.
280 * End of map node event is emitted by invoking {@link #endNode()}. Valid
282 * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
283 * methods will throw {@link IllegalArgumentException}.
286 * name of node as defined in schema, namespace and revision are
287 * derived from parent node.
288 * @param childSizeHint
289 * Non-negative count of expected direct child nodes or
290 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
291 * and should not fail writing of child events, if there are more
293 * @throws IllegalArgumentException
294 * If emitted node is invalid in current context or was emitted
296 * @throws IllegalStateException
297 * If node was emitted inside <code>map</code>,
298 * <code>choice</code> <code>unkeyed list</code> node.
299 * @throws IOException if an underlying IO error occurs
301 void startMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
304 * Emits start of map entry.
307 * End of map entry event is emitted by invoking {@link #endNode()}.
310 * Valid sub-events are:
312 * <li>{@link #leafNode}</li>
313 * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
314 * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
315 * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
316 * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
317 * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
318 * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
323 * QName to value pairs of keys of map entry node. Values MUST BE constant over time.
324 * @param childSizeHint
325 * Non-negative count of expected direct child nodes or
326 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
327 * and should not fail writing of child events, if there are more
329 * @throws IllegalArgumentException
330 * If key contains incorrect value.
331 * @throws IllegalStateException
332 * If node was emitted outside <code>map entry</code> node.
333 * @throws IOException if an underlying IO error occurs
335 void startMapEntryNode(NodeIdentifierWithPredicates identifier, int childSizeHint) throws IOException;
338 * Emits start of map node event.
341 * End of map node event is emitted by invoking {@link #endNode()}. Valid
343 * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
344 * methods will throw {@link IllegalArgumentException}.
347 * name of node as defined in schema, namespace and revision are
348 * derived from parent node.
349 * @param childSizeHint
350 * Non-negative count of expected direct child nodes or
351 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
352 * and should not fail writing of child events, if there are more
354 * @throws IllegalArgumentException
355 * If emitted node is invalid in current context or was emitted
357 * @throws IllegalStateException
358 * If node was emitted inside <code>map</code>,
359 * <code>choice</code> <code>unkeyed list</code> node.
360 * @throws IOException if an underlying IO error occurs
362 void startOrderedMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
365 * Emits start of a choice node event.
368 * name of node as defined in schema, namespace and revision are
369 * derived from parent node.
370 * @param childSizeHint
371 * Non-negative count of expected direct child nodes or
372 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
373 * and should not fail writing of child events, if there are more
375 * @throws IllegalArgumentException
376 * If emitted node is invalid in current context or was emitted
378 * @throws IllegalStateException
379 * If node was emitted inside <code>map</code>,
380 * <code>choice</code> <code>unkeyed list</code> node.
381 * @throws IOException if an underlying IO error occurs
383 void startChoiceNode(NodeIdentifier name, int childSizeHint) throws IOException;
386 * Emits start of augmentation node.
389 * End of augmentation event is emitted by invoking {@link #endNode()}.
392 * Valid sub-events are:
395 * <li>{@link #leafNode}</li>
396 * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
397 * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
398 * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
399 * <li>{@link #startMapNode(NodeIdentifier, int)}</li>
400 * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
404 * Augmentation identifier
405 * @throws IllegalArgumentException
406 * If augmentation is invalid in current context.
407 * @throws IOException if an underlying IO error occurs
409 void startAugmentationNode(AugmentationIdentifier identifier) throws IOException;
412 * Emits anyxml node event.
415 * name of node as defined in schema, namespace and revision are
416 * derived from parent node.
418 * Value of AnyXml node.
419 * @throws IllegalArgumentException
420 * If emitted node is invalid in current context or was emitted
422 * @throws IllegalStateException
423 * If node was emitted inside <code>map</code>,
424 * <code>choice</code> <code>unkeyed list</code> node.
425 * @throws IOException if an underlying IO error occurs
427 void anyxmlNode(NodeIdentifier name, Object value) throws IOException;
430 * Emits start of new yang modeled anyXml node.
433 * End of yang modeled anyXml node event is emitted by invoking {@link #endNode()}.
436 * Valid sub-events are:
438 * <li>{@link #leafNode}</li>
439 * <li>{@link #startContainerNode}</li>
440 * <li>{@link #startLeafSet}</li>
441 * <li>{@link #startMapNode}</li>
442 * <li>{@link #startUnkeyedList}</li>
446 * name of node as defined in schema, namespace and revision are
447 * derived from parent node.
448 * @param childSizeHint
449 * Non-negative count of expected direct child nodes or
450 * {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
451 * and should not fail writing of child events, if there are more
453 * @throws IllegalArgumentException
454 * If emitted node is invalid in current context or was emitted
456 * @throws IllegalStateException
457 * If node was emitted inside <code>map</code>,
458 * <code>choice</code> <code>unkeyed list</code> node.
459 * @throws IOException if an underlying IO error occurs
461 void startYangModeledAnyXmlNode(NodeIdentifier name, int childSizeHint) throws IOException;
464 * Emits end event for node.
466 * @throws IllegalStateException If there is no start* event to be closed.
467 * @throws IOException if an underlying IO error occurs
469 void endNode() throws IOException;
472 * Attach the specified {@link DataSchemaNode} to the next node which will get started or emitted. The default
473 * implementation does nothing.
475 * @param schema DataSchemaNode
476 * @throws NullPointerException if the argument is null
478 default void nextDataSchemaNode(@Nonnull final DataSchemaNode schema) {
479 Preconditions.checkNotNull(schema);
483 void close() throws IOException;
486 void flush() throws IOException;