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