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.ContainerNode;
8 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
9 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
10 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
11 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
12 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
13 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
14 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
15 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
16 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.Module;
18 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
19 import org.w3c.dom.Document;
20 import org.w3c.dom.Element;
22 import javax.xml.parsers.DocumentBuilderFactory;
23 import javax.xml.transform.OutputKeys;
24 import javax.xml.transform.Transformer;
25 import javax.xml.transform.TransformerException;
26 import javax.xml.transform.TransformerFactory;
27 import javax.xml.transform.TransformerFactoryConfigurationError;
28 import javax.xml.transform.dom.DOMSource;
29 import javax.xml.transform.stream.StreamResult;
30 import java.io.ByteArrayInputStream;
31 import java.io.StringWriter;
32 import java.util.Collections;
33 import java.util.List;
36 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
38 * This program and the accompanying materials are made available under the terms of the Eclipse
39 * Public License v1.0 which accompanies this distribution, and is available at
40 * http://www.eclipse.org/legal/epl-v10.html
44 * <code>EncoderDecoderUtil</code> helps in wrapping the NormalizedNode into a SimpleNormalizedNode
45 * protobuf message containing the XML representation of the NormalizeNode
49 public class EncoderDecoderUtil {
50 static DocumentBuilderFactory factory;
52 factory = DocumentBuilderFactory.newInstance();
53 factory.setNamespaceAware(true);
54 factory.setCoalescing(true);
55 factory.setIgnoringElementContentWhitespace(true);
56 factory.setIgnoringComments(true);
59 private static DataSchemaNode findChildNode(Iterable<DataSchemaNode> children,
61 List<DataNodeContainer> containers = Lists.newArrayList();
63 for (DataSchemaNode dataSchemaNode : children) {
64 if (dataSchemaNode.getQName().getLocalName().equals(name))
65 return dataSchemaNode;
66 if (dataSchemaNode instanceof DataNodeContainer) {
67 containers.add((DataNodeContainer) dataSchemaNode);
68 } else if (dataSchemaNode instanceof ChoiceNode) {
69 containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
73 for (DataNodeContainer container : containers) {
74 DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
83 private static DataSchemaNode getSchemaNode(SchemaContext context, QName qname) {
85 for (Module module : context.findModuleByNamespace(qname.getNamespace())) {
86 // we will take the first child as the start of the
87 if (module.getChildNodes() != null || !module.getChildNodes().isEmpty()) {
89 DataSchemaNode found =
90 findChildNode(module.getChildNodes(), qname.getLocalName());
97 private static String toString(Element xml) {
99 Transformer transformer =
100 TransformerFactory.newInstance().newTransformer();
101 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
103 StreamResult result = new StreamResult(new StringWriter());
104 DOMSource source = new DOMSource(xml);
105 transformer.transform(source, result);
107 return result.getWriter().toString();
108 } catch (IllegalArgumentException | TransformerFactoryConfigurationError
109 | TransformerException e) {
110 throw new RuntimeException("Unable to serialize xml element " + xml, e);
115 * Helps in generation of NormalizedNodeXml message for the supplied NormalizedNode
117 * @param sc --SchemaContext
118 * @param normalizedNode -- Normalized Node to be encoded
119 * @return SimpleNormalizedNodeMessage.NormalizedNodeXml
121 public static SimpleNormalizedNodeMessage.NormalizedNodeXml encode(
122 SchemaContext sc, NormalizedNode<?, ?> normalizedNode) {
123 Preconditions.checkArgument(sc != null, "Schema context found null");
124 Preconditions.checkArgument(normalizedNode != null,
125 "normalized node found null");
126 ContainerSchemaNode containerNode =
127 (ContainerSchemaNode) getSchemaNode(sc, normalizedNode.getIdentifier()
129 Preconditions.checkState(containerNode != null,
130 "Couldn't find schema node for " + normalizedNode.getIdentifier());
131 Iterable<Element> els =
132 DomFromNormalizedNodeSerializerFactory
133 .getInstance(XmlDocumentUtils.getDocument(),
134 DomUtils.defaultValueCodecProvider())
135 .getContainerNodeSerializer()
136 .serialize(containerNode, (ContainerNode) normalizedNode);
137 String xmlString = toString(els.iterator().next());
138 SimpleNormalizedNodeMessage.NormalizedNodeXml.Builder builder =
139 SimpleNormalizedNodeMessage.NormalizedNodeXml.newBuilder();
140 builder.setXmlString(xmlString);
141 builder.setNodeIdentifier(((ContainerNode) normalizedNode).getIdentifier()
142 .getNodeType().toString());
143 return builder.build();
148 * Utilizes the SimpleNormalizedNodeMessage.NormalizedNodeXml to convert into NormalizedNode
150 * @param sc -- schema context
151 * @param normalizedNodeXml -- containing the normalized Node XML
152 * @return NormalizedNode return
156 public static NormalizedNode decode(SchemaContext sc,
157 SimpleNormalizedNodeMessage.NormalizedNodeXml normalizedNodeXml)
159 Preconditions.checkArgument(sc != null, "schema context seems to be null");
160 Preconditions.checkArgument(normalizedNodeXml != null,
161 "SimpleNormalizedNodeMessage.NormalizedNodeXml found to be null");
162 QName qname = QName.create(normalizedNodeXml.getNodeIdentifier());
164 // here we will try to get back the NormalizedNode
165 ContainerSchemaNode containerSchemaNode =
166 (ContainerSchemaNode) getSchemaNode(sc, qname);
168 // now we need to read the XML
171 factory.newDocumentBuilder().parse(
172 new ByteArrayInputStream(normalizedNodeXml.getXmlString().getBytes(
174 doc.getDocumentElement().normalize();
176 ContainerNode result =
177 DomToNormalizedNodeParserFactory
178 .getInstance(DomUtils.defaultValueCodecProvider())
179 .getContainerNodeParser()
180 .parse(Collections.singletonList(doc.getDocumentElement()),
181 containerSchemaNode);
183 return (NormalizedNode) result;