+ public final void startLeafNode(final NodeIdentifier name) throws IOException {
+ LOG.trace("Starting a new leaf node");
+ startNode(name, LithiumNode.LEAF_NODE);
+ inSimple = true;
+ }
+
+ @Override
+ public final void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new leaf set");
+ commonStartLeafSet(name, LithiumNode.LEAF_SET);
+ }
+
+ @Override
+ public final void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new ordered leaf set");
+ commonStartLeafSet(name, LithiumNode.ORDERED_LEAF_SET);
+ }
+
+ private void commonStartLeafSet(final NodeIdentifier name, final byte nodeType) throws IOException {
+ startNode(name, nodeType);
+ lastLeafSetQName = name.getNodeType();
+ }
+
+ @Override
+ public final void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
+ LOG.trace("Starting a new leaf set entry node");
+
+ output.writeByte(LithiumNode.LEAF_SET_ENTRY_NODE);
+
+ // lastLeafSetQName is set if the parent LeafSetNode was previously written. Otherwise this is a
+ // stand alone LeafSetEntryNode so write out it's name here.
+ if (lastLeafSetQName == null) {
+ writeQNameInternal(name.getNodeType());
+ }
+ inSimple = true;
+ }
+
+ @Override
+ public final void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new container node");
+ startNode(name, LithiumNode.CONTAINER_NODE);
+ }
+
+ @Override
+ public final void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint)
+ throws IOException {
+ LOG.trace("Starting a new yang modeled anyXml node");
+ startNode(name, LithiumNode.YANG_MODELED_ANY_XML_NODE);
+ }
+
+ @Override
+ public final void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new unkeyed list");
+ startNode(name, LithiumNode.UNKEYED_LIST);
+ }
+
+ @Override
+ public final void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new unkeyed list item");
+ startNode(name, LithiumNode.UNKEYED_LIST_ITEM);
+ }
+
+ @Override
+ public final void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new map node");
+ startNode(name, LithiumNode.MAP_NODE);
+ }
+
+ @Override
+ public final void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
+ throws IOException {
+ LOG.trace("Starting a new map entry node");
+ startNode(identifier, LithiumNode.MAP_ENTRY_NODE);
+ writeKeyValueMap(identifier.entrySet());
+ }
+
+ @Override
+ public final void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new ordered map node");
+ startNode(name, LithiumNode.ORDERED_MAP_NODE);
+ }
+
+ @Override
+ public final void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ LOG.trace("Starting a new choice node");
+ startNode(name, LithiumNode.CHOICE_NODE);
+ }
+
+ @Override
+ public final void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
+ requireNonNull(identifier, "Node identifier should not be null");
+ LOG.trace("Starting a new augmentation node");
+
+ output.writeByte(LithiumNode.AUGMENTATION_NODE);
+ writeAugmentationIdentifier(identifier);
+ }
+
+ @Override
+ public final void startAnyxmlNode(final NodeIdentifier name) throws IOException {
+ LOG.trace("Starting any xml node");
+ startNode(name, LithiumNode.ANY_XML_NODE);
+ inSimple = true;
+ }
+
+ @Override
+ public final void scalarValue(final Object value) throws IOException {
+ writeObject(value);
+ }
+
+ @Override
+ public final void domSourceValue(final DOMSource value) throws IOException {
+ final StringWriter writer = new StringWriter();
+ try {
+ TF.newTransformer().transform(value, new StreamResult(writer));
+ } catch (TransformerException e) {
+ throw new IOException("Error writing anyXml", e);
+ }
+ writeObject(writer.toString());
+ }
+
+ @Override
+ public final void endNode() throws IOException {
+ LOG.trace("Ending the node");
+ if (!inSimple) {
+ lastLeafSetQName = null;
+ output.writeByte(LithiumNode.END_NODE);
+ }
+ inSimple = false;
+ }
+
+ @Override
+ @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST",
+ justification = "The casts in the switch clauses are indirectly confirmed via the determination of 'type'.")
+ final void writePathArgumentInternal(final PathArgument pathArgument) throws IOException {
+ final byte type = LithiumPathArgument.getSerializablePathArgumentType(pathArgument);
+ output.writeByte(type);
+
+ switch (type) {
+ case LithiumPathArgument.NODE_IDENTIFIER:
+ NodeIdentifier nodeIdentifier = (NodeIdentifier) pathArgument;
+ writeQNameInternal(nodeIdentifier.getNodeType());
+ break;
+ case LithiumPathArgument.NODE_IDENTIFIER_WITH_PREDICATES:
+ NodeIdentifierWithPredicates nodeIdentifierWithPredicates =
+ (NodeIdentifierWithPredicates) pathArgument;
+ writeQNameInternal(nodeIdentifierWithPredicates.getNodeType());
+ writeKeyValueMap(nodeIdentifierWithPredicates.entrySet());
+ break;
+ case LithiumPathArgument.NODE_IDENTIFIER_WITH_VALUE:
+ NodeWithValue<?> nodeWithValue = (NodeWithValue<?>) pathArgument;
+ writeQNameInternal(nodeWithValue.getNodeType());
+ writeObject(nodeWithValue.getValue());
+ break;
+ case LithiumPathArgument.AUGMENTATION_IDENTIFIER:
+ // No Qname in augmentation identifier
+ writeAugmentationIdentifier((AugmentationIdentifier) pathArgument);
+ break;
+ default:
+ throw new IllegalStateException("Unknown node identifier type is found : "
+ + pathArgument.getClass().toString());
+ }
+ }
+
+ @Override
+ final void writeYangInstanceIdentifierInternal(final YangInstanceIdentifier identifier) throws IOException {
+ List<PathArgument> pathArguments = identifier.getPathArguments();
+ output.writeInt(pathArguments.size());
+
+ for (PathArgument pathArgument : pathArguments) {
+ writePathArgumentInternal(pathArgument);
+ }
+ }
+
+ final void defaultWriteAugmentationIdentifier(final @NonNull AugmentationIdentifier aid) throws IOException {
+ final Set<QName> qnames = aid.getPossibleChildNames();
+ // Write each child's qname separately, if list is empty send count as 0
+ if (!qnames.isEmpty()) {
+ output.writeInt(qnames.size());
+ for (QName qname : qnames) {
+ writeQNameInternal(qname);
+ }
+ } else {
+ LOG.debug("augmentation node does not have any child");
+ output.writeInt(0);
+ }
+ }
+
+ final void defaultWriteQName(final QName qname) throws IOException {
+ writeString(qname.getLocalName());
+ writeModule(qname.getModule());
+ }
+
+ final void defaultWriteModule(final QNameModule module) throws IOException {
+ writeString(module.getNamespace().toString());
+ final Optional<Revision> revision = module.getRevision();
+ if (revision.isPresent()) {
+ writeString(revision.get().toString());
+ } else {
+ writeByte(LithiumTokens.IS_NULL_VALUE);
+ }
+ }
+
+ abstract void writeModule(QNameModule module) throws IOException;
+
+ abstract void writeAugmentationIdentifier(@NonNull AugmentationIdentifier aid) throws IOException;
+
+ private void startNode(final PathArgument arg, final byte nodeType) throws IOException {
+ requireNonNull(arg, "Node identifier should not be null");
+ checkState(!inSimple, "Attempted to start a child in a simple node");
+
+ // First write the type of node
+ output.writeByte(nodeType);
+ // Write Start Tag
+ writeQNameInternal(arg.getNodeType());
+ }
+
+ private void writeObjSet(final Set<?> set) throws IOException {
+ output.writeInt(set.size());
+ for (Object o : set) {
+ checkArgument(o instanceof String, "Expected value type to be String but was %s (%s)", o.getClass(), o);
+ writeString((String) o);
+ }
+ }
+
+ private void writeObject(final Object value) throws IOException {