1 package org.opendaylight.yangtools.yang.data.impl.codec.xml;
5 import javax.activation.UnsupportedDataTypeException;
6 import javax.xml.parsers.DocumentBuilder;
7 import javax.xml.parsers.DocumentBuilderFactory;
8 import javax.xml.parsers.ParserConfigurationException;
10 import org.opendaylight.yangtools.yang.common.QName;
11 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
12 import org.opendaylight.yangtools.yang.data.api.Node;
13 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
14 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
15 import org.opendaylight.yangtools.yang.model.api.*;
16 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.w3c.dom.Document;
20 import org.w3c.dom.Element;
22 import com.google.common.base.Preconditions;
24 public class XmlDocumentUtils {
26 private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
29 public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(TypeDefinition<?> baseType) {
30 return TypeDefinitionAwareCodec.from(baseType);
34 private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
36 public static Document toDocument(CompositeNode data, DataNodeContainer schema, XmlCodecProvider codecProvider)
37 throws UnsupportedDataTypeException {
38 Preconditions.checkNotNull(data);
39 Preconditions.checkNotNull(schema);
41 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
44 DocumentBuilder bob = dbf.newDocumentBuilder();
45 doc = bob.newDocument();
46 } catch (ParserConfigurationException e) {
50 if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
51 doc.appendChild(createXmlRootElement(doc, data, (SchemaNode) schema, codecProvider));
54 throw new UnsupportedDataTypeException(
55 "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
59 private static Element createXmlRootElement(Document doc, Node<?> data, SchemaNode schema,
60 XmlCodecProvider codecProvider) throws UnsupportedDataTypeException {
61 QName dataType = data.getNodeType();
62 Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
63 if (data instanceof SimpleNode<?>) {
64 if (schema instanceof LeafListSchemaNode) {
65 writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType(),
66 (DataSchemaNode) schema, codecProvider);
67 } else if (schema instanceof LeafSchemaNode) {
68 writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType(),
69 (DataSchemaNode) schema, codecProvider);
71 Object value = data.getValue();
73 itemEl.setTextContent(String.valueOf(value));
76 } else { // CompositeNode
77 for (Node<?> child : ((CompositeNode) data).getChildren()) {
78 DataSchemaNode childSchema = null;
80 childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
81 if (logger.isDebugEnabled()) {
82 if (childSchema == null) {
83 logger.debug("Probably the data node \""
84 + ((child == null) ? "" : child.getNodeType().getLocalName())
85 + "\" is not conform to schema");
89 itemEl.appendChild(createXmlRootElement(doc, child, childSchema, codecProvider));
95 public static void writeValueByType(Element element, SimpleNode<?> node, TypeDefinition<?> type,
96 DataSchemaNode schema, XmlCodecProvider codecProvider) {
98 TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
100 if (baseType instanceof IdentityrefTypeDefinition) {
101 if (node.getValue() instanceof QName) {
102 QName value = (QName) node.getValue();
104 if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
105 prefix = value.getPrefix();
107 element.setAttribute("xmlns:" + prefix, value.getNamespace().toString());
108 element.setTextContent(prefix + ":" + value.getLocalName());
110 logger.debug("Value of {}:{} is not instance of QName but is {}",
111 baseType.getQName().getNamespace(), //
112 baseType.getQName().getLocalName(), //
113 node.getValue().getClass());
114 element.setTextContent(String.valueOf(node.getValue()));
117 if (node.getValue() != null) {
119 String value = codecProvider.codecFor(baseType).serialize(node.getValue());
120 element.setTextContent(value);
121 } catch (ClassCastException e) {
122 element.setTextContent(String.valueOf(node.getValue()));
123 logger.error("Provided node did not have type required by mapping. Using stream instead. {}",e);
129 public final static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
130 TypeDefinition<?> superType = type;
131 while (superType.getBaseType() != null) {
132 superType = superType.getBaseType();
137 private static final DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
138 if (dataSchemaNode != null && node != null) {
139 for (DataSchemaNode dsn : dataSchemaNode) {
140 if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
142 } else if (dsn instanceof ChoiceNode) {
143 for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
144 DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
145 if (foundDsn != null) {
155 public static final XmlCodecProvider defaultValueCodecProvider() {
156 return DEFAULT_XML_VALUE_CODEC_PROVIDER;