2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.remote.rpc.utils;
10 import com.google.common.base.Optional;
11 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
14 import org.opendaylight.yangtools.yang.data.api.Node;
15 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
21 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
22 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
23 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
24 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
25 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.xml.sax.SAXException;
34 import javax.activation.UnsupportedDataTypeException;
35 import javax.annotation.Nonnull;
36 import javax.xml.stream.XMLStreamException;
37 import javax.xml.transform.OutputKeys;
38 import javax.xml.transform.Transformer;
39 import javax.xml.transform.TransformerException;
40 import javax.xml.transform.TransformerFactory;
41 import javax.xml.transform.dom.DOMSource;
42 import javax.xml.transform.stream.StreamResult;
43 import java.io.ByteArrayInputStream;
44 import java.io.IOException;
45 import java.io.StringWriter;
46 import java.util.List;
51 * Common XML-related utility methods, which are not specific to a particular
54 public class XmlUtils {
56 public static final XmlCodecProvider DEFAULT_XML_CODEC_PROVIDER = new XmlCodecProvider() {
58 public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
59 return TypeDefinitionAwareCodec.from(baseType);
65 private static final Logger LOG = LoggerFactory.getLogger(XmlUtils.class);
67 public static String inputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
68 if (cNode == null) return new String();
70 Document domTree = null;
72 Set<RpcDefinition> rpcs = schemaContext.getOperations();
73 for(RpcDefinition rpc : rpcs) {
74 if(rpc.getQName().equals(cNode.getNodeType())){
75 CompositeNode inputContainer = cNode.getFirstCompositeByName(QName.create(cNode.getNodeType(), "input"));
76 domTree = XmlDocumentUtils.toDocument(inputContainer, rpc.getInput(), XmlDocumentUtils.defaultValueCodecProvider());
81 } catch (UnsupportedDataTypeException e) {
82 LOG.error("Error during translation of CompositeNode to Document", e);
84 return domTransformer(domTree);
87 public static String outputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
88 if (cNode == null) return new String();
90 Document domTree = null;
92 Set<RpcDefinition> rpcs = schemaContext.getOperations();
93 for(RpcDefinition rpc : rpcs) {
94 if(rpc.getQName().equals(cNode.getNodeType())){
95 domTree = XmlDocumentUtils.toDocument(cNode, rpc.getOutput(), XmlDocumentUtils.defaultValueCodecProvider());
100 } catch (UnsupportedDataTypeException e) {
101 LOG.error("Error during translation of CompositeNode to Document", e);
103 return domTransformer(domTree);
106 private static String domTransformer(Document domTree) {
107 StringWriter writer = new StringWriter();
109 TransformerFactory tf = TransformerFactory.newInstance();
110 Transformer transformer = tf.newTransformer();
111 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
112 transformer.transform(new DOMSource(domTree), new StreamResult(writer));
113 } catch (TransformerException e) {
115 LOG.error("Error during translation of Document to OutputStream", e);
117 LOG.debug("compositeNodeToXml " + writer.toString());
119 return writer.toString();
122 public static CompositeNode xmlToCompositeNode(String xml){
123 if (xml==null || xml.length()==0) return null;
127 dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
128 } catch (XMLStreamException e) {
129 LOG.error("Error during building data tree from XML", e);
132 if (dataTree == null) {
133 LOG.error("data tree is null");
136 if (dataTree instanceof SimpleNode) {
137 LOG.error("RPC XML was resolved as SimpleNode");
140 return (CompositeNode) dataTree;
143 public static CompositeNode inputXmlToCompositeNode(QName rpc, String xml, SchemaContext schemaContext){
144 if (xml==null || xml.length()==0) return null;
146 CompositeNode compositeNode = null;
149 Document doc = XmlUtil.readXmlToDocument(xml);
150 LOG.debug("xmlToCompositeNode Document is " + xml );
151 Set<RpcDefinition> rpcs = schemaContext.getOperations();
152 for(RpcDefinition rpcDef : rpcs) {
153 if(rpcDef.getQName().equals(rpc)){
154 QName input = rpcDef.getInput().getQName();
155 Element xmlData = (Element) doc.getElementsByTagNameNS(input.getNamespace().toString(), "input").item(0);
156 List<Node<?>> dataNodes = XmlDocumentUtils.toDomNodes(xmlData,
157 Optional.of(rpcDef.getInput().getChildNodes()), schemaContext);
158 final CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
160 it.add(ImmutableCompositeNode.create(input, dataNodes));
161 compositeNode = it.toInstance();
165 } catch (SAXException e) {
166 LOG.error("Error during building data tree from XML", e);
167 } catch (IOException e) {
168 LOG.error("Error during building data tree from XML", e);
171 LOG.debug("xmlToCompositeNode " + compositeNode.toString());
172 return compositeNode;
175 public static TypeDefinition<?> resolveBaseTypeFrom(final @Nonnull TypeDefinition<?> type) {
176 TypeDefinition<?> superType = type;
177 while (superType.getBaseType() != null) {
178 superType = superType.getBaseType();
183 static String encodeIdentifier(final RandomPrefix prefixes, final YangInstanceIdentifier id) {
184 StringBuilder textContent = new StringBuilder();
185 for (PathArgument pathArgument : id.getPathArguments()) {
186 textContent.append('/');
187 textContent.append(prefixes.encodeQName(pathArgument.getNodeType()));
188 if (pathArgument instanceof NodeIdentifierWithPredicates) {
189 Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
191 for (QName keyValue : predicates.keySet()) {
192 Object value = predicates.get(keyValue);
193 String type = value.getClass().getName();
194 String predicateValue = String.valueOf(value);
195 textContent.append('[');
196 textContent.append(prefixes.encodeQName(keyValue));
197 textContent.append("='");
198 textContent.append(predicateValue);
199 textContent.append("@");
200 textContent.append(type);
201 textContent.append("']");
203 } else if (pathArgument instanceof NodeWithValue) {
204 textContent.append("[.='");
205 textContent.append(((NodeWithValue) pathArgument).getValue());
206 textContent.append("']");
210 return textContent.toString();