fbebd2b2de6ae6acfefdbf71f27f96f37bcd47c9
[ccsdk/sli/plugins.git] / restconf-client / provider / src / main / java / org / onap / ccsdk / sli / plugins / yangserializers / dfserializer / DfSerializerUtil.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - CCSDK
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
22
23 import org.dom4j.Element;
24 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
25 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
26 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
27 import org.opendaylight.yangtools.yang.model.api.Module;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
30 import org.w3c.dom.Document;
31 import org.xml.sax.InputSource;
32 import org.xml.sax.SAXException;
33
34 import javax.xml.parsers.DocumentBuilder;
35 import javax.xml.parsers.DocumentBuilderFactory;
36 import javax.xml.parsers.ParserConfigurationException;
37 import javax.xml.transform.Transformer;
38 import javax.xml.transform.TransformerException;
39 import javax.xml.transform.TransformerFactory;
40 import javax.xml.transform.dom.DOMSource;
41 import javax.xml.transform.stream.StreamResult;
42 import java.io.IOException;
43 import java.io.StringReader;
44 import java.io.StringWriter;
45 import java.io.Writer;
46 import java.net.URI;
47 import java.net.URISyntaxException;
48 import java.util.Iterator;
49
50 import static javax.xml.transform.OutputKeys.INDENT;
51 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.OBJECT_NODE;
52 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.TEXT_NODE;
53 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
54
55 /**
56  * Utilities for data format serializer.
57  */
58 public final class DfSerializerUtil {
59
60     static final String JSON_WRITE_ERR = "Unable to write to JSON from " +
61             "properties.";
62
63     static final String NODE_TYPE_ERR = "The node type %s is not supported.";
64
65     static final String JSON_LIS_ERR = "The JSON serializer doesn't have " +
66             "JSON listener";
67
68     static final String XML_LIS_ERR = "The XML serializer doesn't have XML " +
69             "listener";
70
71     static final String JSON_TREE_ERR = "Unable to form JSON tree object from" +
72             " the JSON body provided.";
73
74     static final String XML_TREE_ERR = "Unable to form XML tree object from " +
75             "the XML body provided.";
76
77     static final String FORMAT_ERR = "Only JSON and XML formats are supported" +
78             ". %s is not supported";
79
80     static final String PROP_NODE_ERR = "The property node doesn't have " +
81             "schema node bound to it.";
82
83     static final String DF_ERR = "Type mismatch for the node %s. The schema " +
84             "node does not match with the data format node type %s.";
85
86     static final String UTF_HEADER = "<?xml version=\"1.0\" " +
87             "encoding=\"UTF-8\"?>";
88
89     static final String XML_PREFIX = "yangid";
90
91     private static final String YES = "yes";
92
93     private static final String INDENT_XMLNS = "{http://xml.apache" +
94             ".org/xslt}indent-amount";
95
96     private static final String XML_PARSE_ERR = "Unable to parse the xml to " +
97             "document : \n";
98
99     private static final String URI_ERR = "Unable to parse the URI";
100
101     //No instantiation.
102     private DfSerializerUtil() {
103     }
104
105     /**
106      * Returns the writer which contains the pretty formatted XML string.
107      *
108      * @param input  input XML
109      * @param indent indentation level
110      * @return writer with XML
111      * @throws SvcLogicException when transformation of source fails
112      */
113     static Writer getXmlWriter(String input, String indent) 
114             throws SvcLogicException {
115         try {
116             Transformer transformer = TransformerFactory.newInstance()
117                     .newTransformer();
118             transformer.setOutputProperty(INDENT, YES);
119             transformer.setOutputProperty(INDENT_XMLNS, indent);
120             StreamResult result = new StreamResult(new StringWriter());
121             DOMSource source = new DOMSource(parseXml(input));
122             transformer.transform(source, result);
123             return result.getWriter();
124         } catch (TransformerException e) {
125             throw new SvcLogicException(XML_PARSE_ERR + input, e);
126         }
127     }
128
129     /**
130      * Parses the XML and converts it into dom document which can be used for
131      * formatting the XML.
132      *
133      * @param in input XML
134      * @return dom document of XML
135      * @throws SvcLogicException when document building fails
136      */
137     private static Document parseXml(String in) throws SvcLogicException {
138         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
139         DocumentBuilder db;
140         try {
141             db = dbf.newDocumentBuilder();
142             InputSource is = new InputSource(new StringReader(in));
143             return db.parse(is);
144         } catch (SAXException | IOException | ParserConfigurationException e) {
145             throw new SvcLogicException(XML_PARSE_ERR + in, e);
146         }
147     }
148
149     /**
150      * Returns the resolved namespace object from the input received from the
151      * abstract data format.
152      *
153      * @param mName  module name
154      * @param mUri   module URI
155      * @param ctx    schema context
156      * @param parent parent properties node
157      * @return namespace
158      * @throws SvcLogicException when resolving namespace fails
159      */
160     static Namespace getResolvedNamespace(String mName, String mUri,
161                                           SchemaContext ctx,
162                                           PropertiesNode parent)
163             throws SvcLogicException {
164         if (mName == null && mUri == null) {
165             Namespace parentNs = parent.namespace();
166             return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
167                                  parentNs.revision());
168         }
169
170         Iterator<Module> it;
171         Module mod;
172         if (mName != null) {
173             it = ctx.findModules(mName).iterator();
174         } else {
175             URI modUri = null;
176             try {
177                modUri = new URI(mUri);
178             } catch (URISyntaxException e) {
179                 throw new SvcLogicException(URI_ERR, e);
180             }
181             it = ctx.findModules(modUri).iterator();
182         }
183
184         if (!it.hasNext()) {
185             return null;
186         }
187         mod = it.next();
188
189         return new Namespace(mod.getName(), mod.getQNameModule().getNamespace(),
190                              getRevision(mod.getRevision()));
191     }
192
193     /**
194      * Returns the node type of a XML element.
195      *
196      * @param element XML element
197      * @return node type of the XML element
198      */
199     static XmlNodeType getXmlNodeType(Element element) {
200         Element newElement = element.createCopy();
201         newElement.remove(element.getNamespace());
202         return newElement.hasContent() && newElement.isTextOnly() ?
203                 TEXT_NODE : OBJECT_NODE;
204     }
205
206     /**
207      * Resolves the super type to the base type from type definition.
208      *
209      * @param type super type
210      * @return base type definition
211      */
212     static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
213         TypeDefinition superType = type;
214         while (superType.getBaseType() != null) {
215             superType = superType.getBaseType();
216         }
217         return superType;
218     }
219 }