*/
package org.opendaylight.yangtools.yang.data.impl.codec.xml;
-import com.google.common.base.Preconditions;
+import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX;
+import com.google.common.base.Preconditions;
import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.Deque;
-
-import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
* {@link XMLStreamWriter}, resulting in a RFC 6020 XML encoding.
*/
public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
- private static final XmlStreamUtils UTILS = XmlStreamUtils.create(XmlUtils.DEFAULT_XML_CODEC_PROVIDER);
- private final Deque<Object> schemaStack = new ArrayDeque<>();
private final XMLStreamWriter writer;
- private final DataNodeContainer root;
+ private final SchemaTracker tracker;
+ private final XmlStreamUtils streamUtils;
private XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) {
this.writer = Preconditions.checkNotNull(writer);
-
- DataNodeContainer current = context;
- for (QName qname : path.getPathFromRoot()) {
- final DataSchemaNode child = current.getDataChildByName(qname);
- Preconditions.checkArgument(child instanceof DataNodeContainer);
- current = (DataNodeContainer) child;
- }
-
- this.root = current;
+ this.tracker = SchemaTracker.create(context, path);
+ this.streamUtils = XmlStreamUtils.create(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, context);
}
/**
* @return A new {@link NormalizedNodeStreamWriter}
*/
public static NormalizedNodeStreamWriter create(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) {
- final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
- Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
return new XMLStreamNormalizedNodeStreamWriter(writer, context, path);
}
- private final Object getParent() {
- if (schemaStack.isEmpty()) {
- return root;
+ private void writeStartElement( QName qname) throws XMLStreamException {
+ String ns = qname.getNamespace().toString();
+ String parentNs = writer.getNamespaceContext().getNamespaceURI(DEFAULT_NS_PREFIX);
+ writer.writeStartElement(DEFAULT_NS_PREFIX, qname.getLocalName(), ns);
+ if (!ns.equals(parentNs)) {
+ writer.writeDefaultNamespace(ns);
}
- return schemaStack.peek();
- }
-
- private final SchemaNode getSchema(final PathArgument name) {
- final Object parent = getParent();
- Preconditions.checkState(parent instanceof DataNodeContainer);
-
- final QName qname = name.getNodeType();
- final SchemaNode schema = ((DataNodeContainer)parent).getDataChildByName(qname);
- Preconditions.checkArgument(schema != null, "Could not find schema for node %s", qname);
- return schema;
- }
-
- private void push(final Object schema) {
- schemaStack.push(schema);
}
private void writeElement(final QName qname, final TypeDefinition<?> type, final Object value) throws IOException {
- final String ns = qname.getNamespace().toString();
+ try {
+ writeStartElement(qname);
+ if (value != null) {
+ streamUtils.writeValue(writer, type, value);
+ }
+ writer.writeEndElement();
+ } catch (XMLStreamException e) {
+ throw new IOException("Failed to emit element", e);
+ }
+ }
+ private void writeElement(final QName qname, final SchemaNode schemaNode, final Object value) throws IOException {
try {
+ writeStartElement(qname);
if (value != null) {
- writer.writeStartElement(ns, qname.getLocalName());
- UTILS.writeValue(writer, type, value);
- writer.writeEndElement();
- } else {
- writer.writeEmptyElement(ns, qname.getLocalName());
+ streamUtils.writeValue(writer, schemaNode, value);
}
+ writer.writeEndElement();
} catch (XMLStreamException e) {
throw new IOException("Failed to emit element", e);
}
private void startElement(final QName qname) throws IOException {
try {
- writer.writeStartElement(qname.getNamespace().toString(), qname.getLocalName());
+ writeStartElement(qname);
} catch (XMLStreamException e) {
throw new IOException("Failed to start element", e);
}
}
private void startList(final NodeIdentifier name) {
- final SchemaNode schema = getSchema(name);
- Preconditions.checkArgument(schema instanceof ListSchemaNode, "Node %s is not a list", schema.getPath());
- push(schema);
+ tracker.startList(name);
}
private void startListItem(final PathArgument name) throws IOException {
- final Object schema = getParent();
- Preconditions.checkArgument(schema instanceof ListSchemaNode, "List item is not appropriate");
+ tracker.startListItem(name);
startElement(name.getNodeType());
- push(schema);
}
@Override
public void leafNode(final NodeIdentifier name, final Object value) throws IOException {
- final SchemaNode schema = getSchema(name);
-
- Preconditions.checkArgument(schema instanceof LeafSchemaNode, "Node %s is not a leaf", schema.getPath());
- final TypeDefinition<?> type = ((LeafSchemaNode) schema).getType();
- writeElement(schema.getQName(), type, value);
+ final LeafSchemaNode schema = tracker.leafNode(name);
+ writeElement(schema.getQName(), schema, value);
}
@Override
public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
- final SchemaNode schema = getSchema(name);
-
- Preconditions.checkArgument(schema instanceof LeafListSchemaNode, "Node %s is not a leaf-list", schema.getPath());
- push(schema);
+ tracker.startLeafSet(name);
}
@Override
public void leafSetEntryNode(final Object value) throws IOException {
- final Object parent = getParent();
-
- Preconditions.checkArgument(parent instanceof LeafListSchemaNode, "Not currently in a leaf-list");
- final LeafListSchemaNode schema = (LeafListSchemaNode) parent;
- writeElement(schema.getQName(), schema.getType(), value);
+ final LeafListSchemaNode schema = tracker.leafSetEntryNode();
+ writeElement(schema.getQName(), schema, value);
}
@Override
public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
- final SchemaNode schema = getSchema(name);
- final QName qname = schema.getQName();
-
- Preconditions.checkArgument(schema instanceof ContainerSchemaNode, "Node %s is not a container", schema.getPath());
- startElement(qname);
- push(schema);
+ final SchemaNode schema = tracker.startContainerNode(name);
+ startElement(schema.getQName());
}
@Override
@Override
public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
- final SchemaNode schema = getSchema(name);
-
- Preconditions.checkArgument(schema instanceof ChoiceNode, "Node %s is not a choice", schema.getPath());
- push(schema);
+ tracker.startChoiceNode(name);
}
@Override
- public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
- final Object parent = getParent();
-
- Preconditions.checkArgument(parent instanceof AugmentationTarget, "Augmentation not allowed under %s", parent);
- final AugmentationSchema schema = SchemaUtils.findSchemaForAugment((AugmentationTarget) parent, identifier.getPossibleChildNames());
- push(schema);
+ public void startAugmentationNode(final AugmentationIdentifier identifier) {
+ tracker.startAugmentationNode(identifier);
}
@Override
public void anyxmlNode(final NodeIdentifier name, final Object value) throws IOException {
- final SchemaNode schema = getSchema(name);
-
- Preconditions.checkArgument(schema instanceof AnyXmlSchemaNode, "Node %s is not anyxml", schema.getPath());
-
+ final AnyXmlSchemaNode schema = tracker.anyxmlNode(name);
final QName qname = schema.getQName();
- final String ns = qname.getNamespace().toString();
-
try {
+ writeStartElement(qname);
if (value != null) {
- writer.writeStartElement(ns, qname.getLocalName());
- UTILS.writeValue(writer, (Node<?>)value, schema);
- writer.writeEndElement();
- } else {
- writer.writeEmptyElement(ns, qname.getLocalName());
+ streamUtils.writeValue(writer, (Node<?>)value, schema);
}
+ writer.writeEndElement();
} catch (XMLStreamException e) {
throw new IOException("Failed to emit element", e);
}
@Override
public void endNode() throws IOException {
- final Object schema = schemaStack.pop();
+ final Object schema = tracker.endNode();
try {
if (schema instanceof ListSchemaNode) {
// For lists, we only emit end element on the inner frame
- final Object parent = getParent();
+ final Object parent = tracker.getParent();
if (parent == schema) {
writer.writeEndElement();
}