Push FIXMEs out
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / schema / stream / NormalizedNodeStreamWriter.java
index 059ed1b0e4dbcf48aaa00edc0778fcc2b5a79298..b768b5f27a2b8f4898bfe1a9c11a7f7714d916fa 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.api.schema.stream;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
 import java.io.Closeable;
 import java.io.Flushable;
 import java.io.IOException;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.yang.common.QName;
+import javax.xml.transform.dom.DOMSource;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.ExtensibleObject;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-
 /**
- * Event Stream Writer based on Normalized Node tree representation
+ * Event Stream Writer based on Normalized Node tree representation.
  *
- * <h3>Writing Event Stream</h3>
+ * <h2>Writing Event Stream</h2>
+ * Each entity is emitted by invoking its corresponding {@code start*} event, optionally followed by interior events and
+ * invoking {@link #endNode()}. Some entities supported nested entities, some do not, see below for restrictions.
  *
- * <ul>
- * <li><code>container</code> - Container node representation, start event is
- * emitted using {@link #startContainerNode(NodeIdentifier, int)} and node end event is
- * emitted using {@link #endNode()}. Container node is implementing
- * the org.opendaylight.yangtools.yang.binding.DataObject interface.
- *
- * <li><code>list</code> - YANG list statement has two representation in event
- * stream - unkeyed list and map. Unkeyed list is YANG list which did not
- * specify key.
+ * <p>
+ * While this interface defines basic events, the event stream may be extended through
+ * {@link NormalizedNodeStreamWriterExtension}s discoverable through {@link #getExtensions()} method. The set of these
+ * extensions is immutable during the lifetime of a writer and may be freely cached.
  *
  * <ul>
- * <li><code>Map</code> - Map start event is emitted using
- * {@link #startMapNode(NodeIdentifier, int)} and is ended using {@link #endNode()}. Each map
- * entry start is emitted using {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)} with Map of keys
- * and finished using {@link #endNode()}.</li>
+ * <li>{@code container} - Container node representation, start event is emitted using
+ * {@link #startContainerNode(NodeIdentifier, int)}.
+ * </li>
  *
- * <li><code>UnkeyedList</code> - Unkeyed list represent list without keys,
- * unkeyed list start is emitted using {@link #startUnkeyedList(NodeIdentifier, int)} list
- * end is emitted using {@link #endNode()}. Each list item is emitted using
- * {@link #startUnkeyedListItem(NodeIdentifier, int)} and ended using {@link #endNode()}.</li>
- * </ul></li>
- *
- * <li><code>leaf</code> - Leaf node event is emitted using
- * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted for
- * leaf node.</li>
+ * <li>{@code list} - YANG list statement has two representation in event stream - unkeyed list and map. An unkeyed
+ * list is YANG list which did not specify a {@code key} statement. A map is a {@code list} with a {@code key}
+ * statement.
+ * <ul>
+ * <li>{@code Map} - Map start event is emitted using {@link #startMapNode(NodeIdentifier, int)}. Each map entry start
+ * is emitted using {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
+ * </li>
+ * <li>{@code UnkeyedList} - Unkeyed list represent list without keys, unkeyed list start is emitted using
+ * {@link #startUnkeyedList(NodeIdentifier, int)}. Each list item is emitted using
+ * {@link #startUnkeyedListItem(NodeIdentifier, int)}.</li>
+ * </ul>
+ * </li>
  *
- * <li><code>leaf-list</code> - Leaf list start is emitted using
- * {@link #startLeafSet(NodeIdentifier, int)}. Leaf list end is emitted using
- * {@link #endNode()}. Leaf list entries are emmited using
- * {@link #leafSetEntryNode(QName, Object)}.
+ * <li>{@code leaf} - Leaf node start event is emitted using {@link #startLeafNode(NodeIdentifier)}. Leaf node values
+ * need to be emitted through {@link #scalarValue(Object)}.
+ * </li>
  *
- * <li><code>anyxml - AN node event is emitted using
- * {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted
- * for anyxml node.</code></li>
+ * <li>{@code leaf-list} - Leaf list start is emitted using {@link #startLeafSet(NodeIdentifier, int)}. Individual
+ * leaf-list entries are emitted using {@link #startLeafSetEntryNode(NodeWithValue)}.
  *
+ * <li>{@code anyxml} - An anyxml node event is emitted using {@link #startAnyxmlNode(NodeIdentifier, Class)}.</li>
  *
- * <li><code>choice</code> Choice node event is emmited by
- * {@link #startChoiceNode(NodeIdentifier, int)} event and
- * finished by invoking {@link #endNode()}
- * <li>
- * <code>augment</code> - Represents augmentation, augmentation node is started
- * by invoking {@link #startAugmentationNode(AugmentationIdentifier)} and
- * finished by invoking {@link #endNode()}.</li>
+ * <li>{@code choice} - Choice node event is emitted by {@link #startChoiceNode(NodeIdentifier, int)} event.</li>
  *
+ * <li>{@code augment} - Represents augmentation, augmentation node is started by invoking
+ * {@link #startAugmentationNode(AugmentationIdentifier)}.
+ * </li>
  * </ul>
  *
  * <h3>Implementation notes</h3>
  *
  * <p>
- * Implementations of this interface must not hold user suppled objects
- * and resources needlessly.
- *
+ * Implementations of this interface must not hold user suppled objects and resources needlessly.
  */
-public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
-
+public interface NormalizedNodeStreamWriter extends Closeable, Flushable,
+        ExtensibleObject<NormalizedNodeStreamWriter, NormalizedNodeStreamWriterExtension> {
     /**
-     * Methods in this interface allow users to hint the underlying
-     * implementation about the sizing of container-like constructors
-     * (leafLists, containers, etc.). These hints may be taken into account by a
-     * particular implementation to improve performance, but clients are not
-     * required to provide hints. This constant should be used by clients who
-     * either do not have the sizing information, or do not wish to divulge it
-     * (for whatever reasons). Implementations are free to ignore these hints
-     * completely, but if they do use them, they are expected to be resilient in
-     * face of missing and mismatched hints, which is to say the user can
-     * specify startLeafSet(..., 1) and then call leafNode() 15 times.
+     * Methods in this interface allow users to hint the underlying implementation about the sizing of container-like
+     * constructors (leafLists, containers, etc.). These hints may be taken into account by a particular implementation
+     * to improve performance, but clients are not required to provide hints. This constant should be used by clients
+     * who either do not have the sizing information, or do not wish to divulge it (for whatever reasons).
+     *
+     * <p>
+     * Implementations are free to ignore these hints completely, but if they do use them, they are expected to be
+     * resilient in face of missing and mismatched hints, which is to say the user can specify startLeafSet(..., 1) and
+     * then call leafNode() 15 times.
+     *
      * <p>
-     * The acceptable hint values are non-negative integers and this constant,
-     * all other values will result, based on implementation preference, in the
-     * hint being completely ignored or IllegalArgumentException being thrown.
+     * The acceptable hint values are non-negative integers and this constant, all other values will result, based on
+     * implementation preference, in the hint being completely ignored or IllegalArgumentException being thrown.
      */
     int UNKNOWN_SIZE = -1;
 
     /**
+     * Emits a start of leaf node event.
      *
-     * Emits a leaf node event with supplied value.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param value
-     *            Value of leaf node. v
-     * @throws IllegalArgumentException
-     *             If emitted leaf node has invalid value in current context or
-     *             was emitted multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted leaf node was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
-    void leafNode(NodeIdentifier name, Object value) throws IOException;
+    void startLeafNode(NodeIdentifier name) throws IOException;
 
     /**
-     *
-     * Emits a start of leaf set (leaf-list).
-     * <p>
-     * Emits start of leaf set, during writing leaf set event, only
-     * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
-     * finished by calling {@link #endNode()}.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted leaf node is invalid in current context or was
-     *             emitted multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits a start of system-ordered leaf set (leaf-list). While this entity is open,
+     * only {@link #startLeafSetEntryNode(NodeWithValue)} calls are valid. Implementations are free to reorder entries
+     * within the leaf-list.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted leaf node is invalid in current context or was emitted multiple
+     *                                  times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     *
-     * Emits a start of leaf set (leaf-list).
-     * <p>
-     * Emits start of leaf set, during writing leaf set event, only
-     * {@link #leafSetEntryNode(QName, Object)} calls are valid. Leaf set event is
-     * finished by calling {@link #endNode()}.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted leaf node is invalid in current context or was
-     *             emitted multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits a start of a user-ordered leaf set (leaf-list). While this entity is open, only
+     * {@link #startLeafSetEntryNode(NodeWithValue)} calls are valid. Implementations must retain the same entry order.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted leaf node is invalid in current context or was emitted multiple
+     *                                  times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
-    void startOrderedLeafSet(NodeIdentifier name, int childSizeHint) throws IOException, IllegalArgumentException;
+    void startOrderedLeafSet(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     * Emits a leaf set entry node
+     * Emits a leaf set entry node.
      *
-     * @param name
-     *            name of the node as defined in the schema.
-     * @param value
-     *            Value of leaf set entry node. Supplied object MUST BE constant over time.
-     * @throws IllegalArgumentException
-     *             If emitted leaf node has invalid value.
-     * @throws IllegalStateException
-     *             If node was emitted outside <code>leaf set</code> node.
+     * @param name name of the node as defined in the schema.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException if {@code name} does not match enclosing leaf set entity
+     * @throws IllegalStateException If node was emitted outside {@code leaf set} node.
      * @throws IOException if an underlying IO error occurs
      */
-    void leafSetEntryNode(QName name, Object value) throws IOException;
+    void startLeafSetEntryNode(NodeWithValue<?> name) throws IOException;
 
     /**
-     *
-     * Emits start of new container.
-     *
-     * <p>
-     * End of container event is emitted by invoking {@link #endNode()}.
-     *
-     * <p>
-     * Valid sub-events are:
+     * Emits start of new container. Valid sub-events are:
      * <ul>
-     * <li>{@link #leafNode}</li>
+     * <li>{@link #startLeafNode}</li>
+     * <li>{@link #startAnyxmlNode(NodeIdentifier, Class)}</li>
      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
@@ -202,59 +163,38 @@ public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
      * </ul>
      *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException  If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startContainerNode(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     *
-     * Emits start of unkeyed list node event.
-     *
-     * <p>
-     * End of unkeyed list event is emitted by invoking {@link #endNode()}.
-     * Valid subevents is only {@link #startUnkeyedListItem(NodeIdentifier, int)}. All other
-     * methods will throw {@link IllegalArgumentException}.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits start of unkeyed list node event. Valid subevents is only
+     * {@link #startUnkeyedListItem(NodeIdentifier, int)}.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startUnkeyedList(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     * Emits start of new unkeyed list item.
-     *
-     * <p>
-     * Unkeyed list item event is finished by invoking {@link #endNode()}. Valid
-     * sub-events are:
+     * Emits start of new unkeyed list item. Valid sub-events are:
      * <ul>
-     * <li>{@link #leafNode}</li>
+     * <li>{@link #startLeafNode}</li>
      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
@@ -264,56 +204,35 @@ public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
      * </ul>
      *
      * @param name Identifier of node
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalStateException
-     *             If node was emitted outside <code>unkeyed list</code> node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalStateException If node was emitted outside <code>unkeyed list</code> node.
      * @throws IOException if an underlying IO error occurs
      */
     void startUnkeyedListItem(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     *
-     * Emits start of map node event.
-     *
-     * <p>
-     * End of map node event is emitted by invoking {@link #endNode()}. Valid
-     * subevents is only
-     * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
-     * methods will throw {@link IllegalArgumentException}.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits start of map node event. Valid subevent is only
+     * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     *
-     * Emits start of map entry.
-     *
-     * <p>
-     * End of map entry event is emitted by invoking {@link #endNode()}.
-     *
-     * <p>
-     * Valid sub-events are:
+     * Emits start of map entry. Valid sub-events are:
      * <ul>
-     * <li>{@link #leafNode}</li>
+     * <li>{@link #startLeafNode}</li>
      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
@@ -322,83 +241,52 @@ public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
      * <li>{@link #startAugmentationNode(AugmentationIdentifier)}</li>
      * </ul>
      *
-     *
-     * @param identifier
-     *            QName to value pairs of keys of map entry node. Values  MUST BE constant over time.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If key contains incorrect value.
-     * @throws IllegalStateException
-     *             If node was emitted outside <code>map entry</code> node.
+     * @param identifier QName to value pairs of keys of map entry node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If key contains incorrect value.
+     * @throws IllegalStateException If node was emitted outside {@code map entry} node.
      * @throws IOException if an underlying IO error occurs
      */
     void startMapEntryNode(NodeIdentifierWithPredicates identifier, int childSizeHint) throws IOException;
 
     /**
-     *
-     * Emits start of map node event.
-     *
-     * <p>
-     * End of map node event is emitted by invoking {@link #endNode()}. Valid
-     * subevents is only
-     * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}. All other
-     * methods will throw {@link IllegalArgumentException}.
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits start of map node event.  Valid subevent is only
+     * {@link #startMapEntryNode(NodeIdentifierWithPredicates, int)}.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startOrderedMapNode(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     *
-     *
-     *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param childSizeHint
-     *            Non-negative count of expected direct child nodes or
-     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-     *            and should not fail writing of child events, if there are more
-     *            events than count.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * Emits start of a choice node event.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
      * @throws IOException if an underlying IO error occurs
      */
     void startChoiceNode(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
-     * Emits start of augmentation node.
-     *
-     * <p>
-     * End of augmentation event is emitted by invoking {@link #endNode()}.
-     *
-     * <p>
-     * Valid sub-events are:
-     *
+     * Emits start of augmentation node. Valid sub-events are:
      * <ul>
-     * <li>{@link #leafNode}</li>
+     * <li>{@link #startLeafNode}</li>
      * <li>{@link #startContainerNode(NodeIdentifier, int)}</li>
      * <li>{@link #startChoiceNode(NodeIdentifier, int)}</li>
      * <li>{@link #startLeafSet(NodeIdentifier, int)}</li>
@@ -406,65 +294,74 @@ public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
      * <li>{@link #startUnkeyedList(NodeIdentifier, int)}</li>
      * </ul>
      *
-     * @param identifier
-     *            Augmentation identifier
-     * @throws IllegalArgumentException
-     *             If augmentation is invalid in current context.
+     * @param identifier Augmentation identifier
+     * @throws NullPointerException if {@code identifier} is null
+     * @throws IllegalArgumentException If augmentation is invalid in current context.
      * @throws IOException if an underlying IO error occurs
      */
     void startAugmentationNode(AugmentationIdentifier identifier) throws IOException;
 
     /**
-     * Emits anyxml node event.
+     * Start emitting a new anydata node identified by name.
      *
-     * @param name
-     *            name of node as defined in schema, namespace and revision are
-     *            derived from parent node.
-     * @param value
-     *             Value of AnyXml node.
-     * @throws IllegalArgumentException
-     *             If emitted node is invalid in current context or was emitted
-     *             multiple times.
-     * @throws IllegalStateException
-     *             If node was emitted inside <code>map</code>,
-     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @param name The name of the anydata element
+     * @param objectModel The object model of anydata content
+     * @return True if the specified object model is supported by this extension and the process of emitting the node
+     *         has started. False if the object model is not supported and the node has not started to be emitted.
+     * @throws NullPointerException if any argument is null
      * @throws IOException if an underlying IO error occurs
      */
-    void anyxmlNode(NodeIdentifier name, Object value) throws IOException;
+    @Beta
+    boolean startAnydataNode(NodeIdentifier name, Class<?> objectModel) throws IOException;
 
     /**
-    *
-    * Emits start of new yang modeled anyXml node.
-    *
-    * <p>
-    * End of yang modeled anyXml node event is emitted by invoking {@link #endNode()}.
-    *
-    * <p>
-    * Valid sub-events are:
-    * <ul>
-    * <li>{@link #leafNode}</li>
-    * <li>{@link #startContainerNode}</li>
-    * <li>{@link #startLeafSet}</li>
-    * <li>{@link #startMapNode}</li>
-    * <li>{@link #startUnkeyedList}</li>
-    * </ul>
-    *
-    * @param name
-    *            name of node as defined in schema, namespace and revision are
-    *            derived from parent node.
-    * @param childSizeHint
-    *            Non-negative count of expected direct child nodes or
-    *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
-    *            and should not fail writing of child events, if there are more
-    *            events than count.
-    * @throws IllegalArgumentException
-    *             If emitted node is invalid in current context or was emitted
-    *             multiple times.
-    * @throws IllegalStateException
-    *             If node was emitted inside <code>map</code>,
-    *             <code>choice</code> <code>unkeyed list</code> node.
-    * @throws IOException if an underlying IO error occurs
-    */
+     * Emits a start of anyxml node event.
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param objectModel The object model of anyxml content
+     * @return True if the specified object model is supported by this extension and the process of emitting the node
+     *         has started. False if the object model is not supported and the node has not started to be emitted.
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    boolean startAnyxmlNode(NodeIdentifier name, Class<?> objectModel) throws IOException;
+
+    /**
+     * Set the value of current anyxml node. This call is only valid within the context in which an anyxml node is open.
+     *
+     * @param value node value
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if the argument does not represents a valid value
+     * @throws IllegalStateException if an anyxml node is not open or if it's value has already been set and this
+     *                               implementation does not allow resetting the value.
+     * @throws IOException if an underlying IO error occurs
+     */
+    // FIXME: 7.0.0: this probably should integrated with scalarValue()
+    void domSourceValue(DOMSource value) throws IOException;
+
+    /**
+     * Emits start of new YANG-modeled anyxml node. Valid sub-events are:
+     * <ul>
+     * <li>{@link #startLeafNode}</li>
+     * <li>{@link #startContainerNode}</li>
+     * <li>{@link #startLeafSet}</li>
+     * <li>{@link #startMapNode}</li>
+     * <li>{@link #startUnkeyedList}</li>
+     * </ul>
+     *
+     * @param name name of node as defined in schema, namespace and revision are derived from parent node.
+     * @param childSizeHint Non-negative count of expected direct child nodes or {@link #UNKNOWN_SIZE} if count is
+     *                      unknown. This is only hint and should not fail writing of child events, if there are more
+     *                      events than count.
+     * @throws NullPointerException if {@code name} is null
+     * @throws IllegalArgumentException  If emitted node is invalid in current context or was emitted multiple times.
+     * @throws IllegalStateException If node was emitted inside {@code map}, {@code choice} or a {@code unkeyed list}
+     *                               node.
+     * @throws IOException if an underlying IO error occurs
+     */
     void startYangModeledAnyXmlNode(NodeIdentifier name, int childSizeHint) throws IOException;
 
     /**
@@ -482,10 +379,23 @@ public interface NormalizedNodeStreamWriter extends Closeable, Flushable {
      * @param schema DataSchemaNode
      * @throws NullPointerException if the argument is null
      */
-    default void nextDataSchemaNode(@Nonnull final DataSchemaNode schema) {
-        Preconditions.checkNotNull(schema);
+    default void nextDataSchemaNode(final @NonNull DataSchemaNode schema) {
+        requireNonNull(schema);
     }
 
+    /**
+     * Set the value of current node. This call is only valid within the context in which a value-bearing node is open,
+     * such as a LeafNode, LeafSetEntryNode.
+     *
+     * @param value node value, must be effectively immutable
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if the argument does not represents a valid value
+     * @throws IllegalStateException if a value-bearing node is not open or if it's value has already been set and this
+     *                               implementation does not allow resetting the value.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void scalarValue(@NonNull Object value) throws IOException;
+
     @Override
     void close() throws IOException;