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=02f020c47fdc98307eb4ad2cf9aff0621cfb9529;hb=0c887f9b669e746e92962e0144047c2742f7a60c;hp=3bbb54c70699326453cb6e7e4e4f26fe6ee75dcd;hpb=feaf48f6eaa31b299eb516cd6ca8d65ed9a3246c;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 3bbb54c706..02f020c47f 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,32 +9,38 @@ 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.Collection; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; 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.InstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +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; -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; @@ -44,326 +50,253 @@ 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.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; 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 class XmlDocumentUtils { + private static class ElementWithSchemaContext { + Element element; + SchemaContext schemaContext; - private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() { + ElementWithSchemaContext(final Element element,final SchemaContext schemaContext) { + this.schemaContext = schemaContext; + this.element = element; + } - @Override - public TypeDefinitionAwareCodec> codecFor(TypeDefinition baseType) { - return TypeDefinitionAwareCodec.from(baseType); + 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(); - public static Document toDocument(CompositeNode data, DataNodeContainer schema, XmlCodecProvider codecProvider) + /** + * 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; + } + } + + public static Document getDocument() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); Document doc = null; try { DocumentBuilder bob = dbf.newDocumentBuilder(); doc = bob.newDocument(); } catch (ParserConfigurationException e) { - return null; - } - - 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."); + throw new RuntimeException(e); } + return doc; } - private static Element createXmlRootElement(Document doc, Node data, SchemaNode schema, - 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).getChildren()) { - DataSchemaNode childSchema = null; - if (schema != null) { - childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes()); - 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)); - } + /** + * 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; } - return itemEl; } - private static Element createElementFor(Document doc, 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()); + ret = doc.createElementNS(null, qname.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()); - } - } - return ret; - } - - public static void writeValueByType(Element element, SimpleNode node, TypeDefinition type, - DataSchemaNode schema, XmlCodecProvider codecProvider) { - TypeDefinition baseType = resolveBaseTypeFrom(type); - - if (baseType instanceof IdentityrefTypeDefinition) { - if (node.getValue() instanceof QName) { - QName value = (QName) node.getValue(); - 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 = node.getValue(); - 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 (node.getValue() instanceof InstanceIdentifier) { - // Map< key = namespace, value = prefix> - Map prefixes = new HashMap<>(); - InstanceIdentifier instanceIdentifier = (InstanceIdentifier) node.getValue(); - StringBuilder textContent = new StringBuilder(); - for (PathArgument pathArgument : instanceIdentifier.getPath()) { - textContent.append("/"); - writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), prefixes); - if (pathArgument instanceof NodeIdentifierWithPredicates) { - Map predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues(); - - for (QName keyValue : predicates.keySet()) { - String predicateValue = String.valueOf(predicates.get(keyValue)); - textContent.append("["); - writeIdentifierWithNamespacePrefix(element, textContent, keyValue, prefixes); - textContent.append("='"); - textContent.append(predicateValue); - textContent.append("'"); - textContent.append("]"); - } - } - } - element.setTextContent(textContent.toString()); + if (obj instanceof AttributesContainer) { + final Map attrs = ((AttributesContainer)obj).getAttributes(); - } else { - Object value = node.getValue(); - 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)); + if (attrs != null) { + for (Entry attribute : attrs.entrySet()) { + ret.setAttributeNS(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), + attribute.getValue()); } } - } else { - if (node.getValue() != null) { - final TypeDefinitionAwareCodec codec = codecProvider.codecFor(baseType); - if (codec != null) { - try { - final String text = codec.serialize(node.getValue()); - element.setTextContent(text); - } catch (ClassCastException e) { - logger.error("Provided node did not have type required by mapping. Using stream instead.", e); - element.setTextContent(String.valueOf(node.getValue())); - } - } else { - logger.error("Failed to find codec for {}, falling back to using stream", baseType); - element.setTextContent(String.valueOf(node.getValue())); - } - } - } - } - - private static void writeIdentifierWithNamespacePrefix(Element element, StringBuilder textContent, QName qName, - Map prefixes) { - String namespace = qName.getNamespace().toString(); - String prefix = prefixes.get(namespace); - if (prefix == null) { - prefix = qName.getPrefix(); - if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) { - prefix = generateNewPrefix(prefixes.values()); - } } - element.setAttribute("xmlns:" + prefix, namespace.toString()); - textContent.append(prefix); - prefixes.put(namespace, prefix); - - textContent.append(":"); - textContent.append(qName.getLocalName()); + return ret; } - private static String generateNewPrefix(Collection prefixes) { - StringBuilder result = null; - Random random = new Random(); - do { - result = new StringBuilder(); - for (int i = 0; i < 4; i++) { - int randomNumber = 0x61 + (Math.abs(random.nextInt()) % 26); - result.append(Character.toChars(randomNumber)); - } - } while (prefixes.contains(result.toString())); - - return result.toString(); + public static Element createElementFor(final Document doc, final Node data) { + return createElementFor(doc, data.getNodeType(), data); } - public final static TypeDefinition resolveBaseTypeFrom(TypeDefinition type) { - TypeDefinition superType = type; - while (superType.getBaseType() != null) { - superType = superType.getBaseType(); - } - return superType; + public static Element createElementFor(final Document doc, final NormalizedNode data) { + return createElementFor(doc, data.getNodeType(), data); } - private static final DataSchemaNode findFirstSchemaForNode(Node node, Set dataSchemaNode) { - if (dataSchemaNode != null && node != null) { - for (DataSchemaNode dsn : dataSchemaNode) { - if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) { - return dsn; - } else if (dsn instanceof ChoiceNode) { - for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) { - DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes()); - if (foundDsn != null) { - return foundDsn; - } - } - } - } - } - return null; + public static Node toDomNode(final Element xmlElement, final Optional schema, + final Optional codecProvider) { + return toDomNode(xmlElement, schema, codecProvider, Optional.absent()); } - public static Node toDomNode(Element xmlElement, Optional schema, - Optional codecProvider) { + public static Node toDomNode(final Element xmlElement, final Optional schema, + final Optional codecProvider, final Optional schemaContext) { if (schema.isPresent()) { - return toNodeWithSchema(xmlElement, schema.get(), codecProvider.or(DEFAULT_XML_VALUE_CODEC_PROVIDER)); + if(schemaContext.isPresent()) { + return toNodeWithSchema(xmlElement, schema.get(), codecProvider.or(XmlUtils.DEFAULT_XML_CODEC_PROVIDER), schemaContext.get()); + } else { + return toNodeWithSchema(xmlElement, schema.get(), codecProvider.or(XmlUtils.DEFAULT_XML_CODEC_PROVIDER)); + } } return toDomNode(xmlElement); } - public static CompositeNode fromElement(Element xmlElement) { - CompositeNodeBuilder node = ImmutableCompositeNode.builder(); - node.setQName(qNameFromElement(xmlElement)); - - return node.toInstance(); - } - - private static QName qNameFromElement(Element xmlElement) { + 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(Element xmlElement, DataSchemaNode schema, XmlCodecProvider codecProvider) { + 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); + return toCompositeNodeWithSchema(xmlElement, schema.getQName(), (DataNodeContainer) schema, codecProvider,schemaCtx); } else if (schema instanceof LeafSchemaNode) { - return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider); + return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider,schemaCtx); } else if (schema instanceof LeafListSchemaNode) { - return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider); - + return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider,schemaCtx); } return null; } - private static Node toSimpleNodeWithType(Element xmlElement, LeafSchemaNode schema, - XmlCodecProvider codecProvider) { - TypeDefinitionAwareCodec> codec = codecProvider.codecFor(schema.getType()); + 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; + Object value = null; if (codec != null) { value = codec.deserialize(text); + } + final TypeDefinition baseType = XmlUtils.resolveBaseTypeFrom(schema.getType()); - } else { + if (baseType instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) { + value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx); + } else if(baseType instanceof IdentityrefTypeDefinition){ + value = InstanceIdentifierForXmlCodec.toIdentity(xmlElement.getTextContent(), xmlElement, schemaCtx); + } + + if (value == null) { value = xmlElement.getTextContent(); } - return new SimpleNodeTOImpl(schema.getQName(), null, value); + + Optional modifyAction = getModifyOperationFromAttributes(xmlElement); + return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); } - private static Node toSimpleNodeWithType(Element xmlElement, LeafListSchemaNode schema, - XmlCodecProvider codecProvider) { - TypeDefinitionAwareCodec> codec = codecProvider.codecFor(schema.getType()); + 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; + Object value = null; if (codec != null) { value = codec.deserialize(text); - - } else { + } + if (schema.getType() instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) { + value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx); + } + if (value == null) { value = xmlElement.getTextContent(); } - return new SimpleNodeTOImpl(schema.getQName(), null, value); + + Optional modifyAction = getModifyOperationFromAttributes(xmlElement); + return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); } - private static Node toCompositeNodeWithSchema(Element xmlElement, QName qName, DataNodeContainer schema, - XmlCodecProvider codecProvider) { - List> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes())); - return ImmutableCompositeNode.create(qName, values); + 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) { + return Optional.absent(); + } + + ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue()); + Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement); + + return Optional.of(action); } - private static void checkQName(Element xmlElement, QName qName) { - checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString())); - checkState(qName.getLocalName().equals(xmlElement.getLocalName())); + private static void checkQName(final Element xmlElement, final QName qName) { + checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString()), "Not equal: %s to: %s for: %s and: %s", qName.getNamespace(), xmlElement.getNamespaceURI(), qName, xmlElement); + checkState(qName.getLocalName().equals(xmlElement.getLocalName()), "Not equal: %s to: %s for: %s and: %s", qName.getLocalName(), xmlElement.getLocalName(), qName, xmlElement); } - private static final Optional findFirstSchema(QName qname, Set dataSchemaNode) { - if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) { + public static final 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()) { Optional foundDsn = findFirstSchema(qname, choiceCase.getChildNodes()); - if (foundDsn != null) { + if (foundDsn != null && foundDsn.isPresent()) { return foundDsn; } } @@ -373,11 +306,11 @@ public class XmlDocumentUtils { return Optional.absent(); } - public static Node toDomNode(Document doc) { + public static Node toDomNode(final Document doc) { return toDomNode(doc.getDocumentElement()); } - private static Node toDomNode(Element element) { + private static Node toDomNode(final Element element) { QName qname = qNameFromElement(element); ImmutableList.Builder> values = ImmutableList.> builder(); @@ -403,26 +336,30 @@ public class XmlDocumentUtils { return ImmutableCompositeNode.create(qname, values.build()); } - public static List> toDomNodes(final Element element, final Optional> context) { - return forEachChild(element.getChildNodes(), new Function>>() { + public static List> toDomNodes(final Element element, final Optional> context, final SchemaContext schemaCtx) { + return forEachChild(element.getChildNodes(),schemaCtx, new Function>>() { @Override - public Optional> apply(Element input) { + public Optional> apply(final ElementWithSchemaContext input) { if (context.isPresent()) { - QName partialQName = qNameFromElement(input); + QName partialQName = qNameFromElement(input.getElement()); Optional schemaNode = findFirstSchema(partialQName, context.get()); if (schemaNode.isPresent()) { - return Optional.> fromNullable(// - toNodeWithSchema(input, schemaNode.get(), DEFAULT_XML_VALUE_CODEC_PROVIDER)); + return Optional.> fromNullable( + toNodeWithSchema(input.getElement(), schemaNode.get(), XmlUtils.DEFAULT_XML_CODEC_PROVIDER, input.getSchemaContext())); } } - return Optional.> fromNullable(toDomNode(element)); + 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.
@@ -435,7 +372,7 @@ public class XmlDocumentUtils { * 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 @@ -445,10 +382,9 @@ public class XmlDocumentUtils { * Element with equal notification QName defined in XML Document. */ public static CompositeNode notificationToDomNodes(final Document document, - final Optional> notifications) { + 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) { @@ -457,10 +393,10 @@ public class XmlDocumentUtils { final Optional notificationDef = findNotification(partialQName, notifications.get()); if (notificationDef.isPresent()) { - final Set dataNodes = notificationDef.get().getChildNodes(); + final Iterable dataNodes = notificationDef.get().getChildNodes(); final List> domNodes = toDomNodes(childElement, - Optional.> fromNullable(dataNodes)); - return ImmutableCompositeNode.create(partialQName, domNodes); + Optional.> fromNullable(dataNodes),schemaCtx); + return ImmutableCompositeNode.create(notificationDef.get().getQName(), domNodes); } } } @@ -468,6 +404,11 @@ public class XmlDocumentUtils { 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)) { @@ -480,22 +421,26 @@ public class XmlDocumentUtils { return Optional.absent(); } - private static final List forEachChild(NodeList nodes, Function> forBody) { - ImmutableList.Builder ret = ImmutableList. builder(); - for (int i = 0; i < nodes.getLength(); i++) { + 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((Element) child); + Optional result = forBody.apply(new ElementWithSchemaContext((Element) child,schemaContext)); if (result.isPresent()) { - ret.add(result.get()); + list.add(result.get()); } } } - return ret.build(); + return ImmutableList.copyOf(list); } public static final XmlCodecProvider defaultValueCodecProvider() { - return DEFAULT_XML_VALUE_CODEC_PROVIDER; + return XmlUtils.DEFAULT_XML_CODEC_PROVIDER; } - }