1 package org.opendaylight.controller.cluster.datastore.util;
3 import com.google.common.base.Preconditions;
4 import com.google.common.collect.Lists;
5 import org.opendaylight.controller.protobuff.messages.common.SimpleNormalizedNodeMessage;
6 import org.opendaylight.yangtools.yang.common.QName;
7 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
8 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
9 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
10 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
11 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
12 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
13 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
14 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
15 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
16 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
17 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
18 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
19 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
20 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
21 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.Module;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
32 import javax.xml.parsers.DocumentBuilderFactory;
33 import javax.xml.transform.OutputKeys;
34 import javax.xml.transform.Transformer;
35 import javax.xml.transform.TransformerException;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.TransformerFactoryConfigurationError;
38 import javax.xml.transform.dom.DOMSource;
39 import javax.xml.transform.stream.StreamResult;
40 import java.io.ByteArrayInputStream;
41 import java.io.StringWriter;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.Iterator;
45 import java.util.List;
48 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
50 * This program and the accompanying materials are made available under the terms of the Eclipse
51 * Public License v1.0 which accompanies this distribution, and is available at
52 * http://www.eclipse.org/legal/epl-v10.html
56 * <code>EncoderDecoderUtil</code> helps in wrapping the NormalizedNode into a SimpleNormalizedNode
57 * protobuf message containing the XML representation of the NormalizeNode
61 public class EncoderDecoderUtil {
62 static DocumentBuilderFactory factory;
64 private static DomFromNormalizedNodeSerializerFactory serializerFactory =
65 DomFromNormalizedNodeSerializerFactory
66 .getInstance(XmlDocumentUtils.getDocument(),
67 DomUtils.defaultValueCodecProvider());
69 private static DomToNormalizedNodeParserFactory parserFactory =
70 DomToNormalizedNodeParserFactory
71 .getInstance(DomUtils.defaultValueCodecProvider());
74 factory = DocumentBuilderFactory.newInstance();
75 factory.setNamespaceAware(true);
76 factory.setCoalescing(true);
77 factory.setIgnoringElementContentWhitespace(true);
78 factory.setIgnoringComments(true);
81 private static DataSchemaNode findChildNode(Collection<DataSchemaNode> children,
83 List<DataNodeContainer> containers = Lists.newArrayList();
85 for (DataSchemaNode dataSchemaNode : children) {
86 if (dataSchemaNode.getQName().getLocalName().equals(name))
87 return dataSchemaNode;
88 if (dataSchemaNode instanceof DataNodeContainer) {
89 containers.add((DataNodeContainer) dataSchemaNode);
90 } else if (dataSchemaNode instanceof ChoiceNode) {
91 containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
95 for (DataNodeContainer container : containers) {
96 DataSchemaNode retVal =
97 findChildNode(container.getChildNodes(), name);
106 private static DataSchemaNode getSchemaNode(SchemaContext context,
109 for (Module module : context
110 .findModuleByNamespace(qname.getNamespace())) {
111 // we will take the first child as the start of the
112 if (module.getChildNodes() != null || !module.getChildNodes()
115 DataSchemaNode found =
116 findChildNode(module.getChildNodes(), qname.getLocalName());
123 private static String toString(Element xml) {
125 Transformer transformer =
126 TransformerFactory.newInstance().newTransformer();
127 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
129 StreamResult result = new StreamResult(new StringWriter());
130 DOMSource source = new DOMSource(xml);
131 transformer.transform(source, result);
133 return result.getWriter().toString();
134 } catch (IllegalArgumentException | TransformerFactoryConfigurationError
135 | TransformerException e) {
136 throw new RuntimeException("Unable to serialize xml element " + xml,
141 private static String toString(Iterable<Element> xmlIterable) {
143 Transformer transformer =
144 TransformerFactory.newInstance().newTransformer();
145 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
147 StreamResult result = new StreamResult(new StringWriter());
148 Iterator iterator = xmlIterable.iterator();
150 if(iterator.hasNext()) {
151 source = new DOMSource((org.w3c.dom.Node) iterator.next());
152 transformer.transform(source, result);
153 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
156 while(iterator.hasNext()) {
157 source = new DOMSource((org.w3c.dom.Node) iterator.next());
158 transformer.transform(source, result);
160 System.out.println(result.getWriter().toString());
161 return result.getWriter().toString();
162 } catch (IllegalArgumentException | TransformerFactoryConfigurationError
163 | TransformerException e) {
164 throw new RuntimeException("Unable to serialize xml element(s) " + xmlIterable.toString(),
169 private static Iterable<Element> serialize(DataSchemaNode schemaNode, NormalizedNode normalizedNode){
170 if(schemaNode instanceof ContainerSchemaNode){ //1
171 return serializerFactory
172 .getContainerNodeSerializer()
173 .serialize((ContainerSchemaNode) schemaNode,
174 (ContainerNode) normalizedNode);
175 } else if(schemaNode instanceof ChoiceNode){ //2
176 return serializerFactory
177 .getChoiceNodeSerializer()
178 .serialize((ChoiceNode) schemaNode,
179 (org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) normalizedNode);
180 } else if(schemaNode instanceof LeafSchemaNode){ //3
181 return serializerFactory
182 .getLeafNodeSerializer()
183 .serialize((LeafSchemaNode) schemaNode, (LeafNode) normalizedNode);
184 } else if(schemaNode instanceof ListSchemaNode){ //4
185 return serializerFactory
186 .getMapNodeSerializer()
187 .serialize((ListSchemaNode) schemaNode, (MapNode) normalizedNode);
188 } else if(schemaNode instanceof LeafListSchemaNode){ //5
189 return serializerFactory
190 .getLeafSetNodeSerializer()
191 .serialize((LeafListSchemaNode) schemaNode, (LeafSetNode) normalizedNode);
192 } else if(schemaNode instanceof AugmentationSchema){//6
193 return serializerFactory
194 .getAugmentationNodeSerializer()
195 .serialize((AugmentationSchema) schemaNode, (AugmentationNode) normalizedNode);
196 } else if(schemaNode instanceof ListSchemaNode && normalizedNode instanceof LeafSetEntryNode){ //7
197 return serializerFactory
198 .getLeafSetEntryNodeSerializer()
199 .serialize((LeafListSchemaNode) schemaNode, (LeafSetEntryNode) normalizedNode);
200 } else if(schemaNode instanceof ListSchemaNode){ //8
201 return serializerFactory
202 .getMapEntryNodeSerializer()
203 .serialize((ListSchemaNode) schemaNode, (MapEntryNode) normalizedNode);
208 throw new UnsupportedOperationException(schemaNode.getClass().toString());
211 private static NormalizedNode parse(Document doc, DataSchemaNode schemaNode){
212 if(schemaNode instanceof ContainerSchemaNode){
214 .getContainerNodeParser()
215 .parse(Collections.singletonList(doc.getDocumentElement()),
216 (ContainerSchemaNode) schemaNode);
218 } else if(schemaNode instanceof ChoiceNode){
220 .getChoiceNodeParser()
221 .parse(Collections.singletonList(doc.getDocumentElement()),
222 (ChoiceNode) schemaNode);
223 } else if(schemaNode instanceof LeafNode){
226 .parse(Collections.singletonList(doc.getDocumentElement()),
227 (LeafSchemaNode) schemaNode);
228 } else if(schemaNode instanceof ListSchemaNode){
231 .parse(Collections.singletonList(doc.getDocumentElement()),
232 (ListSchemaNode) schemaNode);
233 } else if(schemaNode instanceof LeafListSchemaNode){
235 .getLeafSetNodeParser()
236 .parse(Collections.singletonList(doc.getDocumentElement()),
237 (LeafListSchemaNode) schemaNode);
238 } else if(schemaNode instanceof AugmentationSchema){
240 .getAugmentationNodeParser()
241 .parse(Collections.singletonList(doc.getDocumentElement()),
242 (AugmentationSchema) schemaNode);
243 } else if(schemaNode instanceof ListSchemaNode){
245 .getMapEntryNodeParser()
246 .parse(Collections.singletonList(doc.getDocumentElement()),
247 (ListSchemaNode) schemaNode);
251 throw new UnsupportedOperationException(schemaNode.getClass().toString());
256 * Helps in generation of NormalizedNodeXml message for the supplied NormalizedNode
258 * @param sc --SchemaContext
259 * @param normalizedNode -- Normalized Node to be encoded
260 * @return SimpleNormalizedNodeMessage.NormalizedNodeXml
262 public static SimpleNormalizedNodeMessage.NormalizedNodeXml encode(
263 SchemaContext sc, NormalizedNode<?, ?> normalizedNode) {
265 Preconditions.checkArgument(sc != null, "Schema context found null");
267 Preconditions.checkArgument(normalizedNode != null,
268 "normalized node found null");
270 DataSchemaNode schemaNode = getSchemaNode(sc,
271 normalizedNode.getIdentifier()
275 Preconditions.checkState(schemaNode != null,
276 "Couldn't find schema node for " + normalizedNode.getIdentifier());
278 Iterable<Element> els = serialize(schemaNode, normalizedNode);
280 String xmlString = toString(els.iterator().next());
281 SimpleNormalizedNodeMessage.NormalizedNodeXml.Builder builder =
282 SimpleNormalizedNodeMessage.NormalizedNodeXml.newBuilder();
283 builder.setXmlString(xmlString);
285 .setNodeIdentifier(normalizedNode.getIdentifier()
286 .getNodeType().toString());
287 return builder.build();
292 * Utilizes the SimpleNormalizedNodeMessage.NormalizedNodeXml to convert into NormalizedNode
294 * @param sc -- schema context
295 * @param normalizedNodeXml -- containing the normalized Node XML
296 * @return NormalizedNode return
300 public static NormalizedNode decode(SchemaContext sc,
301 SimpleNormalizedNodeMessage.NormalizedNodeXml normalizedNodeXml)
305 .checkArgument(sc != null, "schema context seems to be null");
307 Preconditions.checkArgument(normalizedNodeXml != null,
308 "SimpleNormalizedNodeMessage.NormalizedNodeXml found to be null");
309 QName qname = QName.create(normalizedNodeXml.getNodeIdentifier());
311 // here we will try to get back the NormalizedNode
312 DataSchemaNode schemaNode = getSchemaNode(sc, qname);
314 // now we need to read the XML
316 factory.newDocumentBuilder().parse(
317 new ByteArrayInputStream(
318 normalizedNodeXml.getXmlString().getBytes(
322 doc.getDocumentElement().normalize();
325 return parse(doc, schemaNode);