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=19122a00cb18ffdfedfa38f1bcc2d6545b96876b;hb=7fedd460044be8d15547f65b713ecbeec0f74296;hp=eabba23153c65afd9598227429a58ee51dd4e704;hpb=f90d65adfabe80b604c805f56e37fff7c2648199;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 eabba23153..19122a00cb 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 @@ -7,115 +7,31 @@ */ package org.opendaylight.yangtools.yang.data.impl.codec.xml; -import static com.google.common.base.Preconditions.checkState; - +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; 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; - -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.ModifyAction; -import org.opendaylight.yangtools.yang.data.api.Node; 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; -import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; -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.ChoiceSchemaNode; 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; -import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; 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.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -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 final class XmlDocumentUtils { + public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(SchemaContext.NAME, "operation"); -public class XmlDocumentUtils { - private static class ElementWithSchemaContext { - Element element; - SchemaContext schemaContext; - - ElementWithSchemaContext(final Element element,final SchemaContext schemaContext) { - this.schemaContext = schemaContext; - this.element = element; - } - - Element getElement() { - return element; - } - - SchemaContext getSchemaContext() { - return schemaContext; - } - } - - 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(); - - /** - * 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 - * be transformed to root in XML Document. Each element of Data DOM tree is compared against specified Data - * Node Container Schema and transformed accordingly. - * - * @param data Data DOM root element - * @param schema Data Node Container Schema - * @param codecProvider XML Codec Provider - * @return new instance of XML Document - * @throws UnsupportedDataTypeException - */ - public static Document toDocument(final CompositeNode data, final DataNodeContainer schema, final XmlCodecProvider codecProvider) - throws UnsupportedDataTypeException { - Preconditions.checkNotNull(data); - Preconditions.checkNotNull(schema); - - if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) { - throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet."); - } - - final DOMResult result = new DOMResult(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; - } + private XmlDocumentUtils() { + throw new UnsupportedOperationException("Utility class should not be instantiated"); } public static Document getDocument() { @@ -130,30 +46,7 @@ public class XmlDocumentUtils { return doc; } - /** - * Converts Data DOM structure to XML Document for specified XML Codec Provider. The CompositeNode - * data parameter enters as root of Data DOM tree and will be transformed to root in XML Document. The child - * nodes of Data Tree are transformed accordingly. - * - * @param data Data DOM root element - * @param codecProvider XML Codec Provider - * @return new instance of XML Document - * @throws UnsupportedDataTypeException - */ - public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) { - final DOMResult result = new DOMResult(getDocument()); - try { - 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; - } - } - - private static final Element createElementFor(final Document doc, final QName qname, final Object obj) { + private static 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()); @@ -175,100 +68,16 @@ public class XmlDocumentUtils { return ret; } - 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, - final Optional codecProvider) { - if (schema.isPresent()) { - return toNodeWithSchema(xmlElement, schema.get(), codecProvider.or(XmlUtils.DEFAULT_XML_CODEC_PROVIDER)); - } - return toDomNode(xmlElement); - } - - public static CompositeNode fromElement(final Element xmlElement) { - CompositeNodeBuilder node = ImmutableCompositeNode.builder(); - node.setQName(qNameFromElement(xmlElement)); - - return node.toInstance(); - } - public static QName qNameFromElement(final Element xmlElement) { String namespace = xmlElement.getNamespaceURI(); String localName = xmlElement.getLocalName(); return QName.create(namespace != null ? URI.create(namespace) : null, null, localName); } - private static Node toNodeWithSchema(final Element xmlElement, final DataSchemaNode schema, final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) { - checkQName(xmlElement, schema.getQName()); - if (schema instanceof DataNodeContainer) { - return toCompositeNodeWithSchema(xmlElement, schema.getQName(), (DataNodeContainer) schema, codecProvider,schemaCtx); - } else if (schema instanceof LeafSchemaNode) { - return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider,schemaCtx); - } else if (schema instanceof LeafListSchemaNode) { - return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider,schemaCtx); - } - return null; - } - - private static Node toNodeWithSchema(final Element xmlElement, final DataSchemaNode schema, final XmlCodecProvider codecProvider) { - return toNodeWithSchema(xmlElement, schema, codecProvider, null); - } - - protected static Node toSimpleNodeWithType(final Element xmlElement, final LeafSchemaNode schema, - final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) { - TypeDefinitionAwareCodec> codec = codecProvider.codecFor(schema.getType()); - String text = xmlElement.getTextContent(); - Object value = null; - if (codec != null) { - value = codec.deserialize(text); - } - - if (schema.getType() instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) { - value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx); - } else if(schema.getType() instanceof IdentityrefTypeDefinition){ - value = InstanceIdentifierForXmlCodec.toIdentity(xmlElement.getTextContent(), xmlElement, schemaCtx); - } - - if (value == null) { - value = xmlElement.getTextContent(); - } - - Optional modifyAction = getModifyOperationFromAttributes(xmlElement); - return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); - } - - private static Node toSimpleNodeWithType(final Element xmlElement, final LeafListSchemaNode schema, - final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) { - TypeDefinitionAwareCodec> codec = codecProvider.codecFor(schema.getType()); - String text = xmlElement.getTextContent(); - Object value = null; - if (codec != null) { - value = codec.deserialize(text); - } - if (schema.getType() instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) { - value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx); - } - if (value == null) { - value = xmlElement.getTextContent(); - } - - Optional modifyAction = getModifyOperationFromAttributes(xmlElement); - return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); - } - - private static Node toCompositeNodeWithSchema(final Element xmlElement, final QName qName, final DataNodeContainer schema, - final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) { - List> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes()),schemaCtx); - Optional modifyAction = getModifyOperationFromAttributes(xmlElement); - return ImmutableCompositeNode.create(qName, values, modifyAction.orNull()); - } - public static Optional getModifyOperationFromAttributes(final Element xmlElement) { Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName()); if(attributeNodeNS == null) { @@ -281,18 +90,13 @@ public class XmlDocumentUtils { return Optional.of(action); } - private static void checkQName(final Element xmlElement, final QName qName) { - checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString())); - checkState(qName.getLocalName().equals(xmlElement.getLocalName())); - } - - public static final Optional findFirstSchema(final QName qname, final Set dataSchemaNode) { - if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) { + public static Optional findFirstSchema(final QName qname, final Iterable dataSchemaNode) { + if (dataSchemaNode != null && qname != null) { for (DataSchemaNode dsn : dataSchemaNode) { if (qname.isEqualWithoutRevision(dsn.getQName())) { return Optional. of(dsn); - } else if (dsn instanceof ChoiceNode) { - for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) { + } else if (dsn instanceof ChoiceSchemaNode) { + for (ChoiceCaseNode choiceCase : ((ChoiceSchemaNode) dsn).getCases()) { Optional foundDsn = findFirstSchema(qname, choiceCase.getChildNodes()); if (foundDsn != null && foundDsn.isPresent()) { return foundDsn; @@ -304,141 +108,7 @@ public class XmlDocumentUtils { return Optional.absent(); } - public static Node toDomNode(final Document doc) { - return toDomNode(doc.getDocumentElement()); - } - - private static Node toDomNode(final Element element) { - QName qname = qNameFromElement(element); - - ImmutableList.Builder> values = ImmutableList.> builder(); - NodeList nodes = element.getChildNodes(); - boolean isSimpleObject = true; - String value = null; - for (int i = 0; i < nodes.getLength(); i++) { - org.w3c.dom.Node child = nodes.item(i); - if (child instanceof Element) { - isSimpleObject = false; - values.add(toDomNode((Element) child)); - } - if (isSimpleObject && child instanceof org.w3c.dom.Text) { - value = element.getTextContent(); - if (!Strings.isNullOrEmpty(value)) { - isSimpleObject = true; - } - } - } - if (isSimpleObject) { - return new SimpleNodeTOImpl<>(qname, null, value); - } - return ImmutableCompositeNode.create(qname, values.build()); - } - - public static List> toDomNodes(final Element element, final Optional> context,final SchemaContext schemaCtx) { - return forEachChild(element.getChildNodes(),schemaCtx, new Function>>() { - - @Override - public Optional> apply(final ElementWithSchemaContext input) { - if (context.isPresent()) { - QName partialQName = qNameFromElement(input.getElement()); - Optional schemaNode = findFirstSchema(partialQName, context.get()); - if (schemaNode.isPresent()) { - return Optional.> fromNullable(// - toNodeWithSchema(input.getElement(), schemaNode.get(), XmlUtils.DEFAULT_XML_CODEC_PROVIDER, input.getSchemaContext())); - } - } - return Optional.> fromNullable(toDomNode(input.getElement())); - } - - }); - - } - - public static List> toDomNodes(final Element element, final Optional> context) { - return toDomNodes(element,context,null); - } - - /** - * Converts XML Document containing notification data from Netconf device to - * Data DOM Nodes.
- * By specification defined in RFC 6020 - * there are xml elements containing notifications metadata, like eventTime - * or root notification element which specifies namespace for which is - * notification defined in yang model. Those elements MUST be stripped off - * notifications body. This method returns pure notification body which - * begins in element which is equal to notifications name defined in - * corresponding yang model. Rest of notification metadata are obfuscated, - * thus Data DOM contains only pure notification body. - * - * @param document - * XML Document containing notification body - * @param notifications - * Notifications Definition Schema - * @return Data DOM Nodes containing xml notification body definition or - * null if there is no NotificationDefinition with - * Element with equal notification QName defined in XML Document. - */ - public static CompositeNode notificationToDomNodes(final Document document, - final Optional> notifications, final SchemaContext schemaCtx) { - if (notifications.isPresent() && (document != null) && (document.getDocumentElement() != null)) { - final NodeList originChildNodes = document.getDocumentElement().getChildNodes(); - for (int i = 0; i < originChildNodes.getLength(); i++) { - org.w3c.dom.Node child = originChildNodes.item(i); - if (child instanceof Element) { - final Element childElement = (Element) child; - final QName partialQName = qNameFromElement(childElement); - final Optional notificationDef = findNotification(partialQName, - notifications.get()); - if (notificationDef.isPresent()) { - final Set dataNodes = notificationDef.get().getChildNodes(); - final List> domNodes = toDomNodes(childElement, - Optional.> fromNullable(dataNodes),schemaCtx); - return ImmutableCompositeNode.create(notificationDef.get().getQName(), domNodes); - } - } - } - } - return null; - } - - public static CompositeNode notificationToDomNodes(final Document document, - final Optional> notifications) { - return notificationToDomNodes(document, notifications,null); - } - - private static Optional findNotification(final QName notifName, - final Set notifications) { - if ((notifName != null) && (notifications != null)) { - for (final NotificationDefinition notification : notifications) { - if ((notification != null) && notifName.isEqualWithoutRevision(notification.getQName())) { - return Optional.fromNullable(notification); - } - } - } - return Optional.absent(); - } - - private static final List forEachChild(final NodeList nodes, final SchemaContext schemaContext, final Function> forBody) { - final int l = nodes.getLength(); - if (l == 0) { - return ImmutableList.of(); - } - - final List list = new ArrayList<>(l); - for (int i = 0; i < l; i++) { - org.w3c.dom.Node child = nodes.item(i); - if (child instanceof Element) { - Optional result = forBody.apply(new ElementWithSchemaContext((Element) child,schemaContext)); - if (result.isPresent()) { - list.add(result.get()); - } - } - } - return ImmutableList.copyOf(list); - } - - public static final XmlCodecProvider defaultValueCodecProvider() { + public static XmlCodecProvider defaultValueCodecProvider() { return XmlUtils.DEFAULT_XML_CODEC_PROVIDER; } }