/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.data.codec.xml; import com.google.common.base.Strings; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.opendaylight.yangtools.yang.common.QName; 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.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker; import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; final class SchemaAwareXMLStreamNormalizedNodeStreamWriter extends XMLStreamNormalizedNodeStreamWriter<SchemaNode> { private final SchemaTracker tracker; private final XMLStreamWriterUtils streamUtils; private SchemaAwareXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) { super(writer); this.tracker = SchemaTracker.create(context, path); this.streamUtils = XMLStreamWriterUtils.create(context); } static NormalizedNodeStreamWriter newInstance(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) { return new SchemaAwareXMLStreamNormalizedNodeStreamWriter(writer, context, path); } @Override protected void writeAttributes(@Nonnull final Map<QName, String> attributes) throws IOException { for (final Entry<QName, String> qNameStringEntry : attributes.entrySet()) { try { final String namespace = qNameStringEntry.getKey().getNamespace().toString(); if (Strings.isNullOrEmpty(namespace)) { writer.writeAttribute(qNameStringEntry.getKey().getLocalName(), qNameStringEntry.getValue()); } else { writer.writeAttribute(namespace, qNameStringEntry.getKey().getLocalName(), qNameStringEntry.getValue()); } } catch (final XMLStreamException e) { throw new IOException("Unable to emit attribute " + qNameStringEntry, e); } } } @Override protected void writeValue(final XMLStreamWriter xmlWriter, final QName qname, @Nonnull final Object value, final SchemaNode schemaNode) throws IOException, XMLStreamException { streamUtils.writeValue(xmlWriter, schemaNode, value, qname.getModule()); } @Override protected void startList(final NodeIdentifier name) { tracker.startList(name); } @Override protected void startListItem(final PathArgument name) throws IOException { tracker.startListItem(name); startElement(name.getNodeType()); } @Override protected void endNode(final XMLStreamWriter xmlWriter) throws IOException, XMLStreamException { final Object schema = tracker.endNode(); if (schema instanceof ListSchemaNode) { // For lists, we only emit end element on the inner frame final Object parent = tracker.getParent(); if (parent == schema) { xmlWriter.writeEndElement(); } } else if (schema instanceof ContainerSchemaNode) { // Emit container end element xmlWriter.writeEndElement(); } } @Override public void leafNode(final NodeIdentifier name, final Object value) throws IOException { final LeafSchemaNode schema = tracker.leafNode(name); writeElement(schema.getQName(), value, Collections.emptyMap(), schema); } @Override public void leafNode(NodeIdentifier name, Object value, Map<QName, String> attributes) throws IOException { final LeafSchemaNode schema = tracker.leafNode(name); writeElement(schema.getQName(), value, attributes, schema); } @Override public void leafSetEntryNode(final QName name, final Object value, final Map<QName, String> attributes) throws IOException { final LeafListSchemaNode schema = tracker.leafSetEntryNode(name); writeElement(schema.getQName(), value, attributes, schema); } @Override public void leafSetEntryNode(final QName name, final Object value) throws IOException { final LeafListSchemaNode schema = tracker.leafSetEntryNode(name); writeElement(schema.getQName(), value, Collections.emptyMap(), schema); } @Override public void startLeafSet(final NodeIdentifier name, final int childSizeHint) { tracker.startLeafSet(name); } @Override public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) { tracker.startLeafSet(name); } @Override public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException { final SchemaNode schema = tracker.startContainerNode(name); startElement(schema.getQName()); } @Override public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) { tracker.startChoiceNode(name); } @Override public void startAugmentationNode(final AugmentationIdentifier identifier) { tracker.startAugmentationNode(identifier); } @Override public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) throws IOException { final SchemaNode schema = tracker.startYangModeledAnyXmlNode(name); startElement(schema.getQName()); } @Override public void anyxmlNode(final NodeIdentifier name, final Object value) throws IOException { final AnyXmlSchemaNode schema = tracker.anyxmlNode(name); anyxmlNode(schema.getQName(), value); } }