From 78aefba8c580123d0763b483fab81d2a993e32eb Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 11 Sep 2019 22:09:49 +0200 Subject: [PATCH] Move Lithium-specific logic from AbstractNormalizedNodeDataOutput The binding to TokenTypes and co. are really part of AbstractLithiumDataOutput, as different serialization streams versions can use completely different tokens and sizing. Change-Id: I703c1da26ee2f99dee406e4de26db702beb05a06 Signed-off-by: Robert Varga --- .../stream/AbstractLithiumDataOutput.java | 284 ++++++++++++++++-- .../AbstractNormalizedNodeDataOutput.java | 251 +--------------- 2 files changed, 263 insertions(+), 272 deletions(-) diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractLithiumDataOutput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractLithiumDataOutput.java index 07960dd3f6..e8b7547a1e 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractLithiumDataOutput.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractLithiumDataOutput.java @@ -7,26 +7,43 @@ */ package org.opendaylight.controller.cluster.datastore.node.utils.stream; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.DataOutput; import java.io.IOException; +import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.Empty; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.Revision; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +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.data.api.YangInstanceIdentifier.PathArgument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * "original" type mapping. Baseline is Lithium but it really was introduced in Oxygen, where {@code type empty} was @@ -38,6 +55,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; * knowledge. */ abstract class AbstractLithiumDataOutput extends AbstractNormalizedNodeDataOutput { + private static final Logger LOG = LoggerFactory.getLogger(AbstractLithiumDataOutput.class); private static final ImmutableMap, Byte> KNOWN_TYPES = ImmutableMap., Byte>builder() .put(String.class, ValueTypes.STRING_TYPE) .put(Byte.class, ValueTypes.BYTE_TYPE) @@ -52,45 +70,261 @@ abstract class AbstractLithiumDataOutput extends AbstractNormalizedNodeDataOutpu .put(Empty.class, ValueTypes.EMPTY_TYPE) .build(); - private final Map stringCodeMap = new HashMap<>(); + private QName lastLeafSetQName; + private boolean inSimple; + AbstractLithiumDataOutput(final DataOutput output) { super(output); } @Override - final void writeObject(final DataOutput rawOuput, final Object value) throws IOException { + public final void startLeafNode(final NodeIdentifier name) throws IOException { + LOG.trace("Starting a new leaf node"); + startNode(name, NodeTypes.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, NodeTypes.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, NodeTypes.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(NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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, NodeTypes.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(NodeTypes.AUGMENTATION_NODE); + writeAugmentationIdentifier(identifier); + } + + @Override + public final void startAnyxmlNode(final NodeIdentifier name) throws IOException { + LOG.trace("Starting any xml node"); + startNode(name, NodeTypes.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 { + try { + StreamResult xmlOutput = new StreamResult(new StringWriter()); + TransformerFactory.newInstance().newTransformer().transform(value, xmlOutput); + writeObject(xmlOutput.getWriter().toString()); + } catch (TransformerException | TransformerFactoryConfigurationError e) { + throw new IOException("Error writing anyXml", e); + } + } + + @Override + public final void endNode() throws IOException { + LOG.trace("Ending the node"); + if (!inSimple) { + lastLeafSetQName = null; + output.writeByte(NodeTypes.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 = PathArgumentTypes.getSerializablePathArgumentType(pathArgument); + output.writeByte(type); + + switch (type) { + case PathArgumentTypes.NODE_IDENTIFIER: + NodeIdentifier nodeIdentifier = (NodeIdentifier) pathArgument; + writeQNameInternal(nodeIdentifier.getNodeType()); + break; + case PathArgumentTypes.NODE_IDENTIFIER_WITH_PREDICATES: + NodeIdentifierWithPredicates nodeIdentifierWithPredicates = + (NodeIdentifierWithPredicates) pathArgument; + writeQNameInternal(nodeIdentifierWithPredicates.getNodeType()); + writeKeyValueMap(nodeIdentifierWithPredicates.entrySet()); + break; + case PathArgumentTypes.NODE_IDENTIFIER_WITH_VALUE: + NodeWithValue nodeWithValue = (NodeWithValue) pathArgument; + writeQNameInternal(nodeWithValue.getNodeType()); + writeObject(nodeWithValue.getValue()); + break; + case PathArgumentTypes.AUGMENTATION_IDENTIFIER: + // No Qname in augmentation identifier + writeAugmentationIdentifier((AugmentationIdentifier) pathArgument); + break; + default: + throw new IllegalStateException("Unknown node identifier type is found : " + + pathArgument.getClass().toString()); + } + } + + final void defaultWriteAugmentationIdentifier(final @NonNull AugmentationIdentifier aid) throws IOException { + final Set 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 = module.getRevision(); + if (revision.isPresent()) { + writeString(revision.get().toString()); + } else { + writeByte(TokenTypes.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 { byte type = getSerializableType(value); // Write object type first - rawOuput.writeByte(type); + output.writeByte(type); switch (type) { case ValueTypes.BOOL_TYPE: - rawOuput.writeBoolean((Boolean) value); + output.writeBoolean((Boolean) value); break; case ValueTypes.QNAME_TYPE: writeQNameInternal((QName) value); break; case ValueTypes.INT_TYPE: - rawOuput.writeInt((Integer) value); + output.writeInt((Integer) value); break; case ValueTypes.BYTE_TYPE: - rawOuput.writeByte((Byte) value); + output.writeByte((Byte) value); break; case ValueTypes.LONG_TYPE: - rawOuput.writeLong((Long) value); + output.writeLong((Long) value); break; case ValueTypes.SHORT_TYPE: - rawOuput.writeShort((Short) value); + output.writeShort((Short) value); break; case ValueTypes.BITS_TYPE: writeObjSet((Set) value); break; case ValueTypes.BINARY_TYPE: byte[] bytes = (byte[]) value; - rawOuput.writeInt(bytes.length); - rawOuput.write(bytes); + output.writeInt(bytes.length); + output.write(bytes); break; case ValueTypes.YANG_IDENTIFIER_TYPE: writeYangInstanceIdentifierInternal((YangInstanceIdentifier) value); @@ -99,32 +333,28 @@ abstract class AbstractLithiumDataOutput extends AbstractNormalizedNodeDataOutpu break; case ValueTypes.STRING_BYTES_TYPE: final byte[] valueBytes = value.toString().getBytes(StandardCharsets.UTF_8); - rawOuput.writeInt(valueBytes.length); - rawOuput.write(valueBytes); + output.writeInt(valueBytes.length); + output.write(valueBytes); break; default: - rawOuput.writeUTF(value.toString()); + output.writeUTF(value.toString()); break; } } - 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 = module.getRevision(); - if (revision.isPresent()) { - writeString(revision.get().toString()); + private void writeKeyValueMap(final Set> entrySet) throws IOException { + if (!entrySet.isEmpty()) { + output.writeInt(entrySet.size()); + for (Entry entry : entrySet) { + writeQNameInternal(entry.getKey()); + writeObject(entry.getValue()); + } } else { - writeByte(TokenTypes.IS_NULL_VALUE); + output.writeInt(0); } } - @Override - protected final void writeString(final @NonNull String string) throws IOException { + private void writeString(final @NonNull String string) throws IOException { final Integer value = stringCodeMap.get(verifyNotNull(string)); if (value == null) { stringCodeMap.put(string, stringCodeMap.size()); @@ -136,8 +366,6 @@ abstract class AbstractLithiumDataOutput extends AbstractNormalizedNodeDataOutpu } } - abstract void writeModule(QNameModule module) throws IOException; - @VisibleForTesting static final byte getSerializableType(final Object node) { final Byte type = KNOWN_TYPES.get(requireNonNull(node).getClass()); diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java index bb6e97a00e..4c170d7fba 100755 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java @@ -7,37 +7,20 @@ */ package org.opendaylight.controller.cluster.datastore.node.utils.stream; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.DataOutput; import java.io.IOException; import java.io.OutputStream; -import java.io.StringWriter; -import java.util.Collection; -import java.util.Map.Entry; -import java.util.Set; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; +import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -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.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Abstract base class for implementing {@link NormalizedNodeDataOutput} contract. This class uses @@ -49,22 +32,16 @@ import org.slf4j.LoggerFactory; * stream being initialized with a header and version. */ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOutput, NormalizedNodeStreamWriter { - private static final Logger LOG = LoggerFactory.getLogger(AbstractNormalizedNodeDataOutput.class); - - private final DataOutput output; + // Visible for subclasses + final DataOutput output; private NormalizedNodeWriter normalizedNodeWriter; private boolean headerWritten; - private QName lastLeafSetQName; - private boolean inSimple; AbstractNormalizedNodeDataOutput(final DataOutput output) { this.output = requireNonNull(output); } - final DataOutput output() { - return output; - } private void ensureHeaderWritten() throws IOException { if (!headerWritten) { @@ -188,9 +165,9 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut @Override public final void writeSchemaPath(final SchemaPath path) throws IOException { ensureHeaderWritten(); - output.writeBoolean(path.isAbsolute()); - final Collection qnames = path.getPath(); + output.writeBoolean(path.isAbsolute()); + final List qnames = path.getPath(); output.writeInt(qnames.size()); for (QName qname : qnames) { writeQNameInternal(qname); @@ -202,136 +179,6 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut flush(); } - @Override - public void startLeafNode(final NodeIdentifier name) throws IOException { - LOG.trace("Starting a new leaf node"); - startNode(name, NodeTypes.LEAF_NODE); - inSimple = true; - } - - @Override - public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new leaf set"); - commonStartLeafSet(name, NodeTypes.LEAF_SET); - } - - @Override - public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new ordered leaf set"); - commonStartLeafSet(name, NodeTypes.ORDERED_LEAF_SET); - } - - private void commonStartLeafSet(final NodeIdentifier name, final byte nodeType) throws IOException { - startNode(name, nodeType); - lastLeafSetQName = name.getNodeType(); - } - - @Override - public void startLeafSetEntryNode(final NodeWithValue name) throws IOException { - LOG.trace("Starting a new leaf set entry node"); - - output.writeByte(NodeTypes.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 void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new container node"); - startNode(name, NodeTypes.CONTAINER_NODE); - } - - @Override - public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new yang modeled anyXml node"); - startNode(name, NodeTypes.YANG_MODELED_ANY_XML_NODE); - } - - @Override - public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new unkeyed list"); - startNode(name, NodeTypes.UNKEYED_LIST); - } - - @Override - public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new unkeyed list item"); - startNode(name, NodeTypes.UNKEYED_LIST_ITEM); - } - - @Override - public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new map node"); - startNode(name, NodeTypes.MAP_NODE); - } - - @Override - public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) - throws IOException { - LOG.trace("Starting a new map entry node"); - startNode(identifier, NodeTypes.MAP_ENTRY_NODE); - writeKeyValueMap(identifier.entrySet()); - } - - @Override - public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new ordered map node"); - startNode(name, NodeTypes.ORDERED_MAP_NODE); - } - - @Override - public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException { - LOG.trace("Starting a new choice node"); - startNode(name, NodeTypes.CHOICE_NODE); - } - - @Override - public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException { - requireNonNull(identifier, "Node identifier should not be null"); - LOG.trace("Starting a new augmentation node"); - - output.writeByte(NodeTypes.AUGMENTATION_NODE); - writeAugmentationIdentifier(identifier); - } - - @Override - public void startAnyxmlNode(final NodeIdentifier name) throws IOException { - LOG.trace("Starting any xml node"); - startNode(name, NodeTypes.ANY_XML_NODE); - inSimple = true; - } - - @Override - public void scalarValue(final Object value) throws IOException { - writeObject(value); - } - - @Override - public void domSourceValue(final DOMSource value) throws IOException { - try { - StreamResult xmlOutput = new StreamResult(new StringWriter()); - TransformerFactory.newInstance().newTransformer().transform(value, xmlOutput); - writeObject(xmlOutput.getWriter().toString()); - } catch (TransformerException | TransformerFactoryConfigurationError e) { - throw new IOException("Error writing anyXml", e); - } - } - - @Override - public void endNode() throws IOException { - LOG.trace("Ending the node"); - if (!inSimple) { - lastLeafSetQName = null; - output.writeByte(NodeTypes.END_NODE); - } - inSimple = false; - } - @Override public void flush() throws IOException { if (output instanceof OutputStream) { @@ -339,26 +186,8 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut } } - 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()); - } - - final 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); - } - } - final void writeYangInstanceIdentifierInternal(final YangInstanceIdentifier identifier) throws IOException { - Collection pathArguments = identifier.getPathArguments(); + List pathArguments = identifier.getPathArguments(); output.writeInt(pathArguments.size()); for (PathArgument pathArgument : pathArguments) { @@ -366,75 +195,9 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut } } - @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 = PathArgumentTypes.getSerializablePathArgumentType(pathArgument); - output.writeByte(type); - - switch (type) { - case PathArgumentTypes.NODE_IDENTIFIER: - NodeIdentifier nodeIdentifier = (NodeIdentifier) pathArgument; - writeQNameInternal(nodeIdentifier.getNodeType()); - break; - case PathArgumentTypes.NODE_IDENTIFIER_WITH_PREDICATES: - NodeIdentifierWithPredicates nodeIdentifierWithPredicates = - (NodeIdentifierWithPredicates) pathArgument; - writeQNameInternal(nodeIdentifierWithPredicates.getNodeType()); - writeKeyValueMap(nodeIdentifierWithPredicates.entrySet()); - break; - case PathArgumentTypes.NODE_IDENTIFIER_WITH_VALUE: - NodeWithValue nodeWithValue = (NodeWithValue) pathArgument; - writeQNameInternal(nodeWithValue.getNodeType()); - writeObject(nodeWithValue.getValue()); - break; - case PathArgumentTypes.AUGMENTATION_IDENTIFIER: - // No Qname in augmentation identifier - writeAugmentationIdentifier((AugmentationIdentifier) pathArgument); - break; - default: - throw new IllegalStateException("Unknown node identifier type is found : " - + pathArgument.getClass().toString()); - } - } - - private void writeKeyValueMap(final Set> entrySet) throws IOException { - if (!entrySet.isEmpty()) { - output.writeInt(entrySet.size()); - for (Entry entry : entrySet) { - writeQNameInternal(entry.getKey()); - writeObject(entry.getValue()); - } - } else { - output.writeInt(0); - } - } - - final void defaultWriteAugmentationIdentifier(final @NonNull AugmentationIdentifier aid) throws IOException { - final Set 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); - } - } - abstract short streamVersion(); - abstract void writeString(@NonNull String string) throws IOException; - abstract void writeQNameInternal(@NonNull QName qname) throws IOException; - abstract void writeAugmentationIdentifier(@NonNull AugmentationIdentifier aid) throws IOException; - - abstract void writeObject(@NonNull DataOutput output, @NonNull Object value) throws IOException; - - private void writeObject(final Object value) throws IOException { - writeObject(output, value); - } + abstract void writePathArgumentInternal(PathArgument pathArgument) throws IOException; } -- 2.36.6