X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fimpl%2Fcodec%2Fxml%2FXmlDocumentUtils.java;h=a3a2a86e886c5ebcdb2b3e3bc8af1bd81e857332;hb=d5f89a7e2e1237e2e023898562c6630a2d8f8c5e;hp=e011d3ec83bb13b85434c3c2261f061490fe7b57;hpb=a8240131f5b1216d0345a6264a5bde51a21b2b59;p=yangtools.git diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java index e011d3ec83..a3a2a86e88 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java @@ -9,16 +9,10 @@ package org.opendaylight.yangtools.yang.data.impl.codec.xml; import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Function; -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; - import java.net.URI; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -26,14 +20,17 @@ import javax.activation.UnsupportedDataTypeException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.dom.DOMResult; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.AttributesContainer; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.Node; -import org.opendaylight.yangtools.yang.data.api.SimpleNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; @@ -51,7 +48,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; @@ -59,8 +55,14 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; -public class XmlDocumentUtils { +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +public class XmlDocumentUtils { private static class ElementWithSchemaContext { Element element; SchemaContext schemaContext; @@ -79,16 +81,16 @@ public class XmlDocumentUtils { } } + public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation"); + private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class); + private static final XMLOutputFactory FACTORY = XMLOutputFactory.newFactory(); private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() { - @Override public TypeDefinitionAwareCodec> codecFor(final TypeDefinition baseType) { return TypeDefinitionAwareCodec.from(baseType); } }; - private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class); - /** * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will @@ -106,14 +108,20 @@ public class XmlDocumentUtils { Preconditions.checkNotNull(data); Preconditions.checkNotNull(schema); - Document doc = getDocument(); + if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) { + throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet."); + } - if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) { - doc.appendChild(createXmlRootElement(doc, data, (SchemaNode) schema, codecProvider)); - return doc; - } else { - throw new UnsupportedDataTypeException( - "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet."); + final DOMResult result = new DOMResult(); + result.setNode(getDocument()); + try { + final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result); + XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema); + writer.close(); + return (Document)result.getNode(); + } catch (XMLStreamException e) { + logger.error("Failed to serialize data {}", data, e); + return null; } } @@ -139,141 +147,47 @@ public class XmlDocumentUtils { * @return new instance of XML Document * @throws UnsupportedDataTypeException */ - public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) - throws UnsupportedDataTypeException { - Preconditions.checkNotNull(data); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - Document doc = null; + public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) { + final DOMResult result = new DOMResult(); try { - DocumentBuilder bob = dbf.newDocumentBuilder(); - doc = bob.newDocument(); - } catch (ParserConfigurationException e) { + final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result); + XmlStreamUtils.create(codecProvider).writeDocument(writer, data); + writer.close(); + return (Document)result.getNode(); + } catch (XMLStreamException e) { + logger.error("Failed to serialize data {}", data, e); return null; } - - doc.appendChild(createXmlRootElement(doc, data, null, codecProvider)); - return doc; - } - - private static Element createXmlRootElement(final Document doc, final Node data, final SchemaNode schema, - final XmlCodecProvider codecProvider) throws UnsupportedDataTypeException { - Element itemEl = createElementFor(doc, data); - if (data instanceof SimpleNode) { - if (schema instanceof LeafListSchemaNode) { - writeValueByType(itemEl, (SimpleNode) data, ((LeafListSchemaNode) schema).getType(), - (DataSchemaNode) schema, codecProvider); - } else if (schema instanceof LeafSchemaNode) { - writeValueByType(itemEl, (SimpleNode) data, ((LeafSchemaNode) schema).getType(), - (DataSchemaNode) schema, codecProvider); - } else { - Object value = data.getValue(); - if (value != null) { - itemEl.setTextContent(String.valueOf(value)); - } - } - } else { // CompositeNode - for (Node child : ((CompositeNode) data).getValue()) { - DataSchemaNode childSchema = null; - if (schema instanceof DataNodeContainer) { - childSchema = findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull(); - if (logger.isDebugEnabled()) { - if (childSchema == null) { - logger.debug("Probably the data node \"" - + ((child == null) ? "" : child.getNodeType().getLocalName()) - + "\" is not conform to schema"); - } - } - } - itemEl.appendChild(createXmlRootElement(doc, child, childSchema, codecProvider)); - } - } - return itemEl; } - public static Element createElementFor(final Document doc, final Node data) { - QName dataType = data.getNodeType(); - Element ret; - if (dataType.getNamespace() != null) { - ret = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName()); + private static final Element createElementFor(final Document doc, final QName qname, final Object obj) { + final Element ret; + if (qname.getNamespace() != null) { + ret = doc.createElementNS(qname.getNamespace().toString(), qname.getLocalName()); } else { - ret = doc.createElementNS(null, dataType.getLocalName()); - } - if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) { - for (Entry attribute : ((AttributesContainer) data).getAttributes().entrySet()) { - ret.setAttributeNS(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), - attribute.getValue()); - } - + ret = doc.createElementNS(null, qname.getLocalName()); } - return ret; - } - - public static void writeValueByType(final Element element, final SimpleNode node, final TypeDefinition type, - final DataSchemaNode schema, final XmlCodecProvider codecProvider) { - - Object nodeValue = node.getValue(); - writeValueByType(element, type, codecProvider, nodeValue); - } + if (obj instanceof AttributesContainer) { + final Map attrs = ((AttributesContainer)obj).getAttributes(); - public static void writeValueByType(final Element element, final TypeDefinition type, final XmlCodecProvider codecProvider, final Object nodeValue) { - TypeDefinition baseType = resolveBaseTypeFrom(type); - if (baseType instanceof IdentityrefTypeDefinition) { - if (nodeValue instanceof QName) { - QName value = (QName) nodeValue; - String prefix = "x"; - if (value.getPrefix() != null && !value.getPrefix().isEmpty()) { - prefix = value.getPrefix(); - } - element.setAttribute("xmlns:" + prefix, value.getNamespace().toString()); - element.setTextContent(prefix + ":" + value.getLocalName()); - } else { - Object value = nodeValue; - logger.debug("Value of {}:{} is not instance of QName but is {}", baseType.getQName().getNamespace(), - baseType.getQName().getLocalName(), value != null ? value.getClass() : "null"); - if (value != null) { - element.setTextContent(String.valueOf(value)); - } - } - } else if (baseType instanceof InstanceIdentifierTypeDefinition) { - if (nodeValue instanceof InstanceIdentifier) { - InstanceIdentifierForXmlCodec.serialize((InstanceIdentifier)nodeValue,element); - } else { - Object value = nodeValue; - logger.debug("Value of {}:{} is not instance of InstanceIdentifier but is {}", baseType.getQName() - .getNamespace(), // - baseType.getQName().getLocalName(), value != null ? value.getClass() : "null"); - if (value != null) { - element.setTextContent(String.valueOf(value)); - } - } - } else { - if (nodeValue != null) { - final TypeDefinitionAwareCodec codec = codecProvider.codecFor(baseType); - if (codec != null) { - try { - final String text = codec.serialize(nodeValue); - element.setTextContent(text); - } catch (ClassCastException e) { - logger.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", nodeValue, baseType, e); - element.setTextContent(String.valueOf(nodeValue)); - } - } else { - logger.error("Failed to find codec for {}, falling back to using stream", baseType); - element.setTextContent(String.valueOf(nodeValue)); + if (attrs != null) { + for (Entry attribute : attrs.entrySet()) { + ret.setAttributeNS(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), + attribute.getValue()); } } } + + return ret; } - public final static TypeDefinition resolveBaseTypeFrom(final TypeDefinition type) { - TypeDefinition superType = type; - while (superType.getBaseType() != null) { - superType = superType.getBaseType(); - } - return superType; + public static Element createElementFor(final Document doc, final Node data) { + return createElementFor(doc, data.getNodeType(), data); + } + + public static Element createElementFor(final Document doc, final NormalizedNode data) { + return createElementFor(doc, data.getNodeType(), data); } public static Node toDomNode(final Element xmlElement, final Optional schema, @@ -362,13 +276,11 @@ public class XmlDocumentUtils { return ImmutableCompositeNode.create(qName, values, modifyAction.orNull()); } - public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation"); - public static Optional getModifyOperationFromAttributes(final Element xmlElement) { Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName()); if(attributeNodeNS == null) { - return Optional.absent(); - } + return Optional.absent(); + } ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue()); Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement);