4a077e663f187f6d23e05a771d4ec988290c8c90
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / rest / impl / XmlMapper.java
1 package org.opendaylight.controller.sal.rest.impl;
2
3 import java.util.Set;
4
5 import javax.activation.UnsupportedDataTypeException;
6 import javax.xml.parsers.DocumentBuilder;
7 import javax.xml.parsers.DocumentBuilderFactory;
8 import javax.xml.parsers.ParserConfigurationException;
9
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.model.api.ChoiceCaseNode;
15 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
16 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
18 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.YangNode;
24 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.w3c.dom.Document;
28 import org.w3c.dom.Element;
29
30 import com.google.common.base.Preconditions;
31
32 public class XmlMapper {
33     
34     private final Logger logger = LoggerFactory.getLogger(XmlMapper.class); 
35
36     public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
37         Preconditions.checkNotNull(data);
38         Preconditions.checkNotNull(schema);
39
40         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
41         Document doc = null;
42         try {
43             DocumentBuilder bob = dbf.newDocumentBuilder();
44             doc = bob.newDocument();
45         } catch (ParserConfigurationException e) {
46             return null;
47         }
48
49         if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
50             doc.appendChild(translateToXmlAndReturnRootElement(doc, data, schema));
51             return doc;
52         } else {
53             throw new UnsupportedDataTypeException(
54                     "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
55         }
56     }
57
58     private Element translateToXmlAndReturnRootElement(Document doc, Node<?> data, YangNode schema)
59             throws UnsupportedDataTypeException {
60         QName dataType = data.getNodeType();
61         Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
62         if (data instanceof SimpleNode<?>) {
63             if (schema instanceof LeafListSchemaNode) {
64                 writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType());
65             } else if (schema instanceof LeafSchemaNode) {
66                 writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType());
67             } else {
68                 Object value = data.getValue();
69                 if (value != null) {
70                     itemEl.setTextContent(String.valueOf(value));
71                 }
72             }
73         } else { // CompositeNode
74             for (Node<?> child : ((CompositeNode) data).getChildren()) {
75                 DataSchemaNode childSchema = null;
76                 if(schema != null){
77                     childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
78                     if (logger.isDebugEnabled()) {
79                         if (childSchema == null) {
80                             logger.debug("Probably the data node \"" + ((child == null) ? "" : child.getNodeType().getLocalName())
81                                     + "\" is not conform to schema");
82                         }
83                     }
84                 }
85                 itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema));
86             }
87         }
88         return itemEl;
89     }
90
91     private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type) {
92
93         TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
94
95         if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) {
96             QName value = (QName) node.getValue();
97             element.setAttribute("xmlns:x", value.getNamespace().toString());
98             element.setTextContent("x:" + value.getLocalName());
99         } else {
100             Object value = node.getValue();
101             if (value != null) {
102                 element.setTextContent(String.valueOf(value));
103             }
104         }
105     }
106
107     private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
108         if (dataSchemaNode != null && node != null) {
109             for (DataSchemaNode dsn : dataSchemaNode) {
110                 if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
111                     return dsn;
112                 } else if (dsn instanceof ChoiceNode) {
113                     for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
114                         DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
115                         if (foundDsn != null) {
116                             return foundDsn;
117                         }
118                     }
119                 }
120             }
121         }
122         return null;
123     }
124
125     private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
126         return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
127     }
128
129 }