blob: 1b45c12a609f311027b4cc6d6fd400f695194dd4 [file] [log] [blame]
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.odtn.utils;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static java.nio.charset.StandardCharsets.UTF_8;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.io.IOException;
23import java.io.InputStreamReader;
24import java.io.StringWriter;
Ai Hamanobd51cdd2018-10-18 11:30:07 +090025import java.util.List;
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070026
27import javax.xml.parsers.DocumentBuilderFactory;
28import javax.xml.parsers.ParserConfigurationException;
29import javax.xml.transform.OutputKeys;
30import javax.xml.transform.Transformer;
31import javax.xml.transform.TransformerException;
32import javax.xml.transform.TransformerFactory;
33import javax.xml.transform.dom.DOMSource;
34import javax.xml.transform.stream.StreamResult;
35
Ray Milkeyd84f89b2018-08-17 14:54:17 -070036import org.osgi.service.component.annotations.Activate;
37import org.osgi.service.component.annotations.Component;
38import org.osgi.service.component.annotations.Deactivate;
39import org.osgi.service.component.annotations.Reference;
40import org.osgi.service.component.annotations.ReferenceCardinality;
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070041import org.onlab.osgi.DefaultServiceDirectory;
42import org.onosproject.yang.model.DataNode;
43import org.onosproject.yang.model.DefaultModelObjectData;
44import org.onosproject.yang.model.DefaultResourceData;
45import org.onosproject.yang.model.InnerNode;
46import org.onosproject.yang.model.ModelConverter;
47import org.onosproject.yang.model.ModelObject;
48import org.onosproject.yang.model.ModelObjectData;
49import org.onosproject.yang.model.ResourceData;
50import org.onosproject.yang.model.ResourceId;
Ai Hamanobd51cdd2018-10-18 11:30:07 +090051import org.onosproject.yang.runtime.AnnotatedNodeInfo;
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070052import org.onosproject.yang.runtime.CompositeData;
53import org.onosproject.yang.runtime.CompositeStream;
54import org.onosproject.yang.runtime.DefaultCompositeData;
55import org.onosproject.yang.runtime.DefaultRuntimeContext;
56import org.onosproject.yang.runtime.RuntimeContext;
57import org.onosproject.yang.runtime.YangRuntimeService;
58import org.slf4j.Logger;
59import org.w3c.dom.Document;
60import org.xml.sax.InputSource;
61import org.xml.sax.SAXException;
62
63import com.fasterxml.jackson.core.JsonProcessingException;
64import com.fasterxml.jackson.databind.JsonNode;
65import com.fasterxml.jackson.databind.ObjectMapper;
66import com.fasterxml.jackson.databind.SerializationFeature;
67import com.google.common.annotations.Beta;
Yuta HIGUCHId0f8d892018-04-09 12:14:00 -070068import com.google.common.io.CharSource;
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070069import com.google.common.io.CharStreams;
70
71@Beta
72@Component(immediate = true)
73public class YangToolUtil {
74 private static final Logger log = getLogger(YangToolUtil.class);
75
Ray Milkeyd84f89b2018-08-17 14:54:17 -070076 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070077 protected YangRuntimeService yangRuntimeService;
78 protected static YangRuntimeService yrs;
79
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -070081 protected ModelConverter modelConverter;
82 protected static ModelConverter converter;
83
84 @Activate
85 protected void activate() {
86 yrs = yangRuntimeService;
87 converter = modelConverter;
88 log.info("Started");
89 }
90
91 @Deactivate
92 protected void deactivate() {
93 log.info("Stopped");
94 }
95
96 protected static void initStaticContext() {
97 if (yrs == null) {
98 yrs = DefaultServiceDirectory.getService(YangRuntimeService.class);
99 }
100 if (converter == null) {
101 converter = DefaultServiceDirectory.getService(ModelConverter.class);
102 }
103 }
104
105 /**
106 * Converts XML Document into CharSequence.
107 *
108 * @param xmlInput to convert
109 * @return CharSequence
110 */
111 public static CharSequence toCharSequence(Document xmlInput) {
112 return toCharSequence(xmlInput, true);
113 }
114
115 /**
116 * Converts XML Document into CharSequence.
117 *
118 * @param xmlInput to convert
119 * @param omitXmlDecl or not
120 * @return CharSequence
121 */
122 public static CharSequence toCharSequence(Document xmlInput, boolean omitXmlDecl) {
123 try {
124 TransformerFactory tf = TransformerFactory.newInstance();
125 Transformer transformer = tf.newTransformer();
126 if (omitXmlDecl) {
127 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
128 }
129 StringWriter writer = new StringWriter();
130 transformer.transform(new DOMSource(xmlInput), new StreamResult(writer));
131 return writer.getBuffer();
132 } catch (TransformerException e) {
133 log.error("Exception thrown", e);
134 return null;
135 }
136 }
137
138 /**
139 * Converts JsonNode into CharSequence.
140 *
141 * @param jsonInput to convert
142 * @return CharSequence
143 */
144 public static CharSequence toCharSequence(JsonNode jsonInput) {
145 checkNotNull(jsonInput);
146 ObjectMapper mapper = new ObjectMapper();
147 // TODO following pretty printing option should be removed
148 mapper.enable(SerializationFeature.INDENT_OUTPUT);
149
150 try {
151 return mapper.writerWithDefaultPrettyPrinter()
Yuta HIGUCHId0f8d892018-04-09 12:14:00 -0700152 .writeValueAsString(jsonInput);
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700153 } catch (JsonProcessingException e) {
154 log.error("Exception thrown", e);
155 return null;
156 }
157 }
158
159 /**
160 * Converts UTF-8 CompositeStream into CharSequence.
161 *
162 * @param utf8Input to convert
163 * @return CharSequence
164 */
165 public static CharSequence toCharSequence(CompositeStream utf8Input) {
166 StringBuilder s = new StringBuilder();
167 try {
168 CharStreams.copy(new InputStreamReader(utf8Input.resourceData(), UTF_8), s);
169 return s;
170 } catch (IOException e) {
171 log.error("Exception thrown", e);
172 return null;
173 }
174 }
175
176 /**
177 * Converts JSON CompositeStream into JsonNode.
178 *
179 * @param jsonInput to convert
180 * @return JsonNode
181 */
182 public static JsonNode toJsonNode(CompositeStream jsonInput) {
183 ObjectMapper mapper = new ObjectMapper();
184 try {
185 return mapper.readTree(jsonInput.resourceData());
186 } catch (IOException e) {
187 log.error("Exception thrown", e);
188 return null;
189 }
190 }
191
192 /**
193 * Converts XML CompositeStream into XML Document.
194 *
195 * @param xmlInput to convert
196 * @return Document
197 */
198 public static Document toDocument(CompositeStream xmlInput) {
199 try {
200 return DocumentBuilderFactory.newInstance()
201 .newDocumentBuilder()
202 .parse(new InputSource(new InputStreamReader(xmlInput.resourceData(), UTF_8)));
203 } catch (ParserConfigurationException | SAXException | IOException e) {
204 log.error("Exception thrown", e);
205 return null;
206 }
207 }
208
209 /**
Yuta HIGUCHId0f8d892018-04-09 12:14:00 -0700210 * Converts XML source into XML Document.
211 *
212 * @param xmlInput to convert
213 * @return Document
214 */
215 public static Document toDocument(CharSource xmlInput) {
216 try {
217 return DocumentBuilderFactory.newInstance()
218 .newDocumentBuilder()
219 .parse(new InputSource(xmlInput.openStream()));
220 } catch (ParserConfigurationException | SAXException | IOException e) {
221 log.error("Exception thrown", e);
222 return null;
223 }
224 }
225
226 /**
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700227 * Converts CompositeData into XML CompositeStream.
228 *
229 * @param input CompositeData to convert
230 * @return XML CompositeStream
231 */
232 public static CompositeStream toXmlCompositeStream(CompositeData input) {
233 initStaticContext();
234 RuntimeContext yrtContext = new DefaultRuntimeContext.Builder()
235 .setDataFormat("xml")
236 // Following does not have any effect?
237 //.addAnnotation(XMLNS_XC_ANNOTATION)
238 .build();
239 CompositeStream xml = yrs.encode(input, yrtContext);
240 return xml;
241 }
242
243 /**
244 * Converts CompositeData into JSON CompositeStream.
245 *
246 * @param input CompositeData to convert
247 * @return JSON CompositeStream
248 */
249 public static CompositeStream toJsonCompositeStream(CompositeData input) {
250 initStaticContext();
251 RuntimeContext yrtContext = new DefaultRuntimeContext.Builder()
252 .setDataFormat("JSON")
253 .build();
254 CompositeStream xml = yrs.encode(input, yrtContext);
255 return xml;
256 }
257
258 /**
259 * Converts ResourceData into CompositeData.
260 *
261 * @param input ResourceData to convert
262 * @return CompositeData
263 */
264 public static CompositeData toCompositeData(ResourceData input) {
265 CompositeData.Builder builder =
266 DefaultCompositeData.builder();
267 builder.resourceData(input);
268 // remove, merge, replace, ...
269 //builder.addAnnotatedNodeInfo(info)
270
271 return builder.build();
272 }
273
274 /**
Ai Hamanobd51cdd2018-10-18 11:30:07 +0900275 * Converts ResourceData & AnnotatedNodeInfo into CompositeData.
276 *
277 * @param input ResourceData to convert
278 * @param annotatedNodeInfos AnnotatedNodeInfoList to convert
279 * @return CompositeData
280 */
281 public static CompositeData toCompositeData(
282 ResourceData input,
283 List<AnnotatedNodeInfo> annotatedNodeInfos) {
284 CompositeData.Builder builder =
285 DefaultCompositeData.builder();
286 builder.resourceData(input);
287
288 // Set AnnotationNodeInfo
289 annotatedNodeInfos.stream()
290 .forEach(a -> builder.addAnnotatedNodeInfo(a));
291
292 return builder.build();
293 }
294
295 /**
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700296 * Converts DataNode into ResourceData.
297 *
298 * @param resourceId pointing to parent of {@code dataNode}, YANG-wise.
299 * @param dataNode to convert, must be InnerNode
300 * @return ResourceData
301 */
302 public static ResourceData toResourceData(ResourceId resourceId, DataNode dataNode) {
303 DefaultResourceData.Builder builder = DefaultResourceData.builder();
304 builder.resourceId(checkNotNull(resourceId));
305 if (dataNode instanceof InnerNode) {
Yuta HIGUCHIf84c91a2018-06-03 22:19:38 -0700306 builder.addDataNode(dataNode);
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700307 } else {
308 log.error("Unexpected DataNode encountered {}", dataNode);
309 }
310 return builder.build();
311 }
312
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700313 /**
314 * Converts ModelObject into a DataNode.
315 *
316 * @param input ModelOject
317 * @return DataNode
318 */
319 public static DataNode toDataNode(ModelObject input) {
hirokib8ddc3f2018-06-02 08:29:42 -0700320 // FIXME this converter will work with root-level nodes only.
Yuta HIGUCHI48f4cb72018-03-29 20:30:56 -0700321 initStaticContext();
322 ModelObjectData modelData = DefaultModelObjectData.builder()
323 .addModelObject(input)
324 .identifier(null)
325 .build();
326
327 ResourceData rnode = converter.createDataNode(modelData);
328 if (rnode.dataNodes().isEmpty()) {
329 log.error("input did not result in any datanode. {}", input);
330 return null;
331 }
332 return rnode.dataNodes().get(0);
333 }
334}