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=262a48a93385579c74061d497ea11c0abcdcb18a;hb=5feac31a11a337a0c840f73c5c4612a6c997fa2a;hp=9e999be49197b1a0a9ec75c6d7f230e5d01ac466;hpb=f3c2a12a9127b60accce86f83d335d9c7634452f;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 9e999be491..262a48a933 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,8 +9,17 @@ 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; @@ -18,16 +27,20 @@ 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.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; @@ -36,260 +49,244 @@ 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 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; } - }; - private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class); + SchemaContext getSchemaContext() { + return schemaContext; + } + } - public static Document toDocument(CompositeNode data, DataNodeContainer schema, XmlCodecProvider codecProvider) + 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; + } + } + + 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()); - } - 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(Element element, SimpleNode node, TypeDefinition type, - DataSchemaNode schema, XmlCodecProvider codecProvider) { + if (obj instanceof AttributesContainer) { + final Map attrs = ((AttributesContainer)obj).getAttributes(); - 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 (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())); + 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(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); } - 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 Element createElementFor(final Document doc, final NormalizedNode data) { + return createElementFor(doc, data.getNodeType(), data); } - public static Node toDomNode(Element xmlElement, Optional schema, - Optional codecProvider) { + public static Node toDomNode(final Element xmlElement, final Optional schema, + final Optional codecProvider) { if (schema.isPresent()) { - return toNodeWithSchema(xmlElement, schema.get(), codecProvider.or(DEFAULT_XML_VALUE_CODEC_PROVIDER)); + 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); + } - } else { + 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(); } - 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()); } - private static void checkQName(Element xmlElement, QName qName) { + 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(final Element xmlElement, final QName qName) { checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString())); checkState(qName.getLocalName().equals(xmlElement.getLocalName())); } - 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; } } @@ -299,11 +296,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(); @@ -329,42 +326,111 @@ 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())); } }); } - private static final List forEachChild(NodeList nodes, Function> forBody) { - ImmutableList.Builder ret = ImmutableList. builder(); - for (int i = 0; i < nodes.getLength(); i++) { + 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 Iterable 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((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; } - }