3 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
11 package org.opendaylight.controller.cluster.datastore.util;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Lists;
15 import org.opendaylight.controller.protobuff.messages.common.SimpleNormalizedNodeMessage;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
20 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
25 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
26 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
27 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
28 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
29 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
30 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
31 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
33 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.Module;
38 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
42 import javax.xml.parsers.DocumentBuilderFactory;
43 import javax.xml.transform.OutputKeys;
44 import javax.xml.transform.Transformer;
45 import javax.xml.transform.TransformerException;
46 import javax.xml.transform.TransformerFactory;
47 import javax.xml.transform.TransformerFactoryConfigurationError;
48 import javax.xml.transform.dom.DOMSource;
49 import javax.xml.transform.stream.StreamResult;
50 import java.io.ByteArrayInputStream;
51 import java.io.StringWriter;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.Iterator;
55 import java.util.List;
59 * <code>EncoderDecoderUtil</code> helps in wrapping the NormalizedNode into a SimpleNormalizedNode
60 * protobuf message containing the XML representation of the NormalizeNode
64 public class EncoderDecoderUtil {
65 static DocumentBuilderFactory factory;
67 private static DomFromNormalizedNodeSerializerFactory serializerFactory =
68 DomFromNormalizedNodeSerializerFactory
69 .getInstance(XmlDocumentUtils.getDocument(),
70 DomUtils.defaultValueCodecProvider());
72 private static DomToNormalizedNodeParserFactory parserFactory =
73 DomToNormalizedNodeParserFactory
74 .getInstance(DomUtils.defaultValueCodecProvider());
77 factory = DocumentBuilderFactory.newInstance();
78 factory.setNamespaceAware(true);
79 factory.setCoalescing(true);
80 factory.setIgnoringElementContentWhitespace(true);
81 factory.setIgnoringComments(true);
84 private static DataSchemaNode findChildNode(Collection<DataSchemaNode> children,
86 List<DataNodeContainer> containers = Lists.newArrayList();
88 for (DataSchemaNode dataSchemaNode : children) {
89 if (dataSchemaNode.getQName().getLocalName().equals(name))
90 return dataSchemaNode;
91 if (dataSchemaNode instanceof DataNodeContainer) {
92 containers.add((DataNodeContainer) dataSchemaNode);
93 } else if (dataSchemaNode instanceof ChoiceNode) {
94 containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
98 for (DataNodeContainer container : containers) {
99 DataSchemaNode retVal =
100 findChildNode(container.getChildNodes(), name);
101 if (retVal != null) {
109 private static DataSchemaNode getSchemaNode(SchemaContext context,
112 for (Module module : context
113 .findModuleByNamespace(qname.getNamespace())) {
114 // we will take the first child as the start of the
115 if (module.getChildNodes() != null || !module.getChildNodes()
118 DataSchemaNode found =
119 findChildNode(module.getChildNodes(), qname.getLocalName());
126 private static String toString(Element xml) {
128 Transformer transformer =
129 TransformerFactory.newInstance().newTransformer();
130 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
132 StreamResult result = new StreamResult(new StringWriter());
133 DOMSource source = new DOMSource(xml);
134 transformer.transform(source, result);
136 return result.getWriter().toString();
137 } catch (IllegalArgumentException | TransformerFactoryConfigurationError
138 | TransformerException e) {
139 throw new RuntimeException("Unable to serialize xml element " + xml,
144 private static String toString(Iterable<Element> xmlIterable) {
146 Transformer transformer =
147 TransformerFactory.newInstance().newTransformer();
148 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
150 StreamResult result = new StreamResult(new StringWriter());
151 Iterator iterator = xmlIterable.iterator();
153 if(iterator.hasNext()) {
154 source = new DOMSource((org.w3c.dom.Node) iterator.next());
155 transformer.transform(source, result);
156 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
159 while(iterator.hasNext()) {
160 source = new DOMSource((org.w3c.dom.Node) iterator.next());
161 transformer.transform(source, result);
163 System.out.println(result.getWriter().toString());
164 return result.getWriter().toString();
165 } catch (IllegalArgumentException | TransformerFactoryConfigurationError
166 | TransformerException e) {
167 throw new RuntimeException("Unable to serialize xml element(s) " + xmlIterable.toString(),
172 private static Iterable<Element> serialize(DataSchemaNode schemaNode, NormalizedNode normalizedNode){
173 if(schemaNode instanceof ContainerSchemaNode){ //1
174 return serializerFactory
175 .getContainerNodeSerializer()
176 .serialize((ContainerSchemaNode) schemaNode,
177 (ContainerNode) normalizedNode);
178 } else if(schemaNode instanceof ChoiceNode){ //2
179 return serializerFactory
180 .getChoiceNodeSerializer()
181 .serialize((ChoiceNode) schemaNode,
182 (org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) normalizedNode);
183 } else if(schemaNode instanceof LeafSchemaNode){ //3
184 return serializerFactory
185 .getLeafNodeSerializer()
186 .serialize((LeafSchemaNode) schemaNode, (LeafNode) normalizedNode);
187 } else if(schemaNode instanceof ListSchemaNode){ //4
188 return serializerFactory
189 .getMapNodeSerializer()
190 .serialize((ListSchemaNode) schemaNode, (MapNode) normalizedNode);
191 } else if(schemaNode instanceof LeafListSchemaNode){ //5
192 return serializerFactory
193 .getLeafSetNodeSerializer()
194 .serialize((LeafListSchemaNode) schemaNode, (LeafSetNode) normalizedNode);
195 } else if(schemaNode instanceof AugmentationSchema){//6
196 return serializerFactory
197 .getAugmentationNodeSerializer()
198 .serialize((AugmentationSchema) schemaNode, (AugmentationNode) normalizedNode);
199 } else if(schemaNode instanceof ListSchemaNode && normalizedNode instanceof LeafSetEntryNode){ //7
200 return serializerFactory
201 .getLeafSetEntryNodeSerializer()
202 .serialize((LeafListSchemaNode) schemaNode, (LeafSetEntryNode) normalizedNode);
203 } else if(schemaNode instanceof ListSchemaNode){ //8
204 return serializerFactory
205 .getMapEntryNodeSerializer()
206 .serialize((ListSchemaNode) schemaNode, (MapEntryNode) normalizedNode);
211 throw new UnsupportedOperationException(schemaNode.getClass().toString());
214 private static NormalizedNode parse(Document doc, DataSchemaNode schemaNode){
215 if(schemaNode instanceof ContainerSchemaNode){
217 .getContainerNodeParser()
218 .parse(Collections.singletonList(doc.getDocumentElement()),
219 (ContainerSchemaNode) schemaNode);
221 } else if(schemaNode instanceof ChoiceNode){
223 .getChoiceNodeParser()
224 .parse(Collections.singletonList(doc.getDocumentElement()),
225 (ChoiceNode) schemaNode);
226 } else if(schemaNode instanceof LeafNode){
229 .parse(Collections.singletonList(doc.getDocumentElement()),
230 (LeafSchemaNode) schemaNode);
231 } else if(schemaNode instanceof ListSchemaNode){
234 .parse(Collections.singletonList(doc.getDocumentElement()),
235 (ListSchemaNode) schemaNode);
236 } else if(schemaNode instanceof LeafListSchemaNode){
238 .getLeafSetNodeParser()
239 .parse(Collections.singletonList(doc.getDocumentElement()),
240 (LeafListSchemaNode) schemaNode);
241 } else if(schemaNode instanceof AugmentationSchema){
243 .getAugmentationNodeParser()
244 .parse(Collections.singletonList(doc.getDocumentElement()),
245 (AugmentationSchema) schemaNode);
246 } else if(schemaNode instanceof ListSchemaNode){
248 .getMapEntryNodeParser()
249 .parse(Collections.singletonList(doc.getDocumentElement()),
250 (ListSchemaNode) schemaNode);
254 throw new UnsupportedOperationException(schemaNode.getClass().toString());
259 * Helps in generation of NormalizedNodeXml message for the supplied NormalizedNode
261 * @param sc --SchemaContext
262 * @param normalizedNode -- Normalized Node to be encoded
263 * @return SimpleNormalizedNodeMessage.NormalizedNodeXml
265 public static SimpleNormalizedNodeMessage.NormalizedNodeXml encode(
266 SchemaContext sc, NormalizedNode<?, ?> normalizedNode) {
268 Preconditions.checkArgument(sc != null, "Schema context found null");
270 Preconditions.checkArgument(normalizedNode != null,
271 "normalized node found null");
273 DataSchemaNode schemaNode = getSchemaNode(sc,
274 normalizedNode.getIdentifier()
278 Preconditions.checkState(schemaNode != null,
279 "Couldn't find schema node for " + normalizedNode.getIdentifier());
281 Iterable<Element> els = serialize(schemaNode, normalizedNode);
283 String xmlString = toString(els.iterator().next());
284 SimpleNormalizedNodeMessage.NormalizedNodeXml.Builder builder =
285 SimpleNormalizedNodeMessage.NormalizedNodeXml.newBuilder();
286 builder.setXmlString(xmlString);
288 .setNodeIdentifier(normalizedNode.getIdentifier()
289 .getNodeType().toString());
290 return builder.build();
295 * Utilizes the SimpleNormalizedNodeMessage.NormalizedNodeXml to convert into NormalizedNode
297 * @param sc -- schema context
298 * @param normalizedNodeXml -- containing the normalized Node XML
299 * @return NormalizedNode return
303 public static NormalizedNode decode(SchemaContext sc,
304 SimpleNormalizedNodeMessage.NormalizedNodeXml normalizedNodeXml)
308 .checkArgument(sc != null, "schema context seems to be null");
310 Preconditions.checkArgument(normalizedNodeXml != null,
311 "SimpleNormalizedNodeMessage.NormalizedNodeXml found to be null");
312 QName qname = QName.create(normalizedNodeXml.getNodeIdentifier());
314 // here we will try to get back the NormalizedNode
315 DataSchemaNode schemaNode = getSchemaNode(sc, qname);
317 // now we need to read the XML
319 factory.newDocumentBuilder().parse(
320 new ByteArrayInputStream(
321 normalizedNodeXml.getXmlString().getBytes(
325 doc.getDocumentElement().normalize();
328 return parse(doc, schemaNode);