- restconf client implementation using RuntimeGeneratedMappingService
[yangtools.git] / restconf / restconf-util / src / main / java / org / opendaylight / yangtools / restconf / utils / RestconfUtils.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.restconf.utils;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.BiMap;
13 import com.google.common.collect.HashBiMap;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.net.URI;
17 import java.net.URLEncoder;
18 import java.util.AbstractMap.SimpleEntry;
19 import java.util.Arrays;
20 import java.util.Date;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.ParserConfigurationException;
29 import org.eclipse.xtend2.lib.StringConcatenation;
30 import org.eclipse.xtext.xbase.lib.Functions;
31 import org.eclipse.xtext.xbase.lib.IterableExtensions;
32 import org.opendaylight.yangtools.yang.binding.DataObject;
33 import org.opendaylight.yangtools.yang.binding.RpcService;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
39 import org.opendaylight.yangtools.yang.data.api.Node;
40 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
41 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
42 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
43 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
44 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
46 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.Module;
49 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
54 import org.xml.sax.SAXException;
55
56 public class RestconfUtils {
57
58     private static final Logger logger = LoggerFactory.getLogger(RestconfUtils.class);
59
60     private static final BiMap<URI,String> uriToModuleName = new Functions.Function0<BiMap<URI,String>>() {
61         @Override
62         public BiMap<URI,String> apply() {
63             HashBiMap<URI,String> _create = HashBiMap.<URI, String>create();
64             return _create;
65         }
66     }.apply();
67
68
69     public static Entry<String,DataSchemaNode> toRestconfIdentifier(org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> bindingIdentifier, BindingIndependentMappingService mappingService, SchemaContext schemaContext) {
70         InstanceIdentifier domIdentifier = mappingService.toDataDom(bindingIdentifier);
71         return toRestconfIdentifier(domIdentifier, schemaContext);
72
73     }
74
75     public static Entry<String,DataSchemaNode> toRestconfIdentifier(
76             InstanceIdentifier xmlInstanceIdentifier,
77             SchemaContext schemaContext) {
78
79         final List<InstanceIdentifier.PathArgument> elements = xmlInstanceIdentifier.getPath();
80         final StringBuilder ret = new StringBuilder();
81         InstanceIdentifier.PathArgument _head = IterableExtensions.<InstanceIdentifier.PathArgument>head(elements);
82         final QName startQName = _head.getNodeType();
83         URI _namespace = startQName.getNamespace();
84         Date _revision = startQName.getRevision();
85         final Module initialModule = schemaContext.findModuleByNamespaceAndRevision(_namespace, _revision);
86         DataNodeContainer node = (initialModule);
87         DataSchemaNode schemaNode = null;
88         for (final InstanceIdentifier.PathArgument element : elements) {
89             {
90                 final DataSchemaNode potentialNode = node.getDataChildByName(element.getNodeType());
91                 if (!isListOrContainer(potentialNode)) {
92                     return null;
93                 }
94                 node = ((DataNodeContainer) potentialNode);
95                 schemaNode = potentialNode;
96                 ret.append(convertToRestconfIdentifier(element, node,schemaContext));
97             }
98         }
99         return new SimpleEntry<>(ret.toString(),schemaNode);
100     }
101
102     private static CharSequence convertContainerToRestconfIdentifier(final InstanceIdentifier.NodeIdentifier argument, final ContainerSchemaNode node, SchemaContext schemaContext) {
103         StringConcatenation _builder = new StringConcatenation();
104         _builder.append("/");
105         QName _nodeType = argument.getNodeType();
106         CharSequence _restconfIdentifier = toRestconfIdentifier(_nodeType,schemaContext);
107         _builder.append(_restconfIdentifier, "");
108         return _builder;
109     }
110     private static CharSequence convertListToRestconfIdentifier(final InstanceIdentifier.NodeIdentifierWithPredicates argument, final ListSchemaNode node,SchemaContext schemaContext) {
111         QName _nodeType = argument.getNodeType();
112         final CharSequence nodeIdentifier = toRestconfIdentifier(_nodeType,schemaContext);
113         final Map<QName,Object> keyValues = argument.getKeyValues();
114         StringConcatenation _builder = new StringConcatenation();
115         _builder.append("/");
116         _builder.append(nodeIdentifier, "");
117         _builder.append("/");
118         {
119             List<QName> _keyDefinition = node.getKeyDefinition();
120             boolean _hasElements = false;
121             for(final QName key : _keyDefinition) {
122                 if (!_hasElements) {
123                     _hasElements = true;
124                 } else {
125                     _builder.appendImmediate("/", "");
126                 }
127                 Object _get = keyValues.get(key);
128                 String _uriString = toUriString(_get);
129                 _builder.append(_uriString, "");
130             }
131         }
132         return _builder;
133     }
134     private static String toUriString(final Object object) {
135         boolean _tripleEquals = (object == null);
136         if (_tripleEquals) {
137             return "";
138         }
139         String _string = object.toString();
140         return URLEncoder.encode(_string);
141     }
142
143     public static CharSequence toRestconfIdentifier(final QName qname,SchemaContext schemaContext) {
144         URI _namespace = qname.getNamespace();
145         String module = uriToModuleName.get(_namespace);
146         boolean _tripleEquals = (module == null);
147         if (_tripleEquals) {
148             URI _namespace_1 = qname.getNamespace();
149             Date _revision = qname.getRevision();
150             final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(_namespace_1, _revision);
151             boolean _tripleEquals_1 = (moduleSchema == null);
152             if (_tripleEquals_1) {
153                 return null;
154             }
155             URI _namespace_2 = qname.getNamespace();
156             String _name = moduleSchema.getName();
157             uriToModuleName.put(_namespace_2, _name);
158             String _name_1 = moduleSchema.getName();
159             module = _name_1;
160         }
161         StringConcatenation _builder = new StringConcatenation();
162         _builder.append(module, "");
163         _builder.append(":");
164         String _localName = qname.getLocalName();
165         _builder.append(_localName, "");
166         return _builder;
167     }
168     private static CharSequence convertToRestconfIdentifier(final InstanceIdentifier.PathArgument argument, final DataNodeContainer node, SchemaContext schemaContext) {
169         if (argument instanceof InstanceIdentifier.NodeIdentifier
170                 && node instanceof ContainerSchemaNode) {
171             return convertContainerToRestconfIdentifier((NodeIdentifier)argument, (ContainerSchemaNode) node,schemaContext);
172         } else if (argument instanceof InstanceIdentifier.NodeIdentifierWithPredicates
173                 && node instanceof ListSchemaNode) {
174             return convertListToRestconfIdentifier((NodeIdentifierWithPredicates) argument,(ListSchemaNode) node,schemaContext);
175         }  else {
176             throw new IllegalArgumentException("Unhandled parameter types: " +
177                     Arrays.<Object>asList(argument, node).toString());
178         }
179     }
180     private static boolean isListOrContainer(final DataSchemaNode node) {
181         boolean _or = false;
182         if ((node instanceof ListSchemaNode)) {
183             _or = true;
184         } else {
185             _or = ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode));
186         }
187         return _or;
188     }
189
190     public static Module findModuleByNamespace(final URI namespace,SchemaContext schemaContext) {
191         boolean _tripleNotEquals = (namespace != null);
192         Preconditions.checkArgument(_tripleNotEquals);
193         final Set<Module> moduleSchemas = schemaContext.findModuleByNamespace(namespace);
194         Module _filterLatestModule = null;
195         if (moduleSchemas!=null) {
196             _filterLatestModule=filterLatestModule(moduleSchemas);
197         }
198         return _filterLatestModule;
199     }
200
201     private static Module filterLatestModule(final Iterable<Module> modules) {
202         Module latestModule = IterableExtensions.<Module>head(modules);
203         for (final Module module : modules) {
204             Date _revision = module.getRevision();
205             Date _revision_1 = latestModule.getRevision();
206             boolean _after = _revision.after(_revision_1);
207             if (_after) {
208                 latestModule = module;
209             }
210         }
211         return latestModule;
212     }
213
214     public String findModuleNameByNamespace(final URI namespace,SchemaContext schemaContext) {
215         String moduleName = this.uriToModuleName.get(namespace);
216         boolean _tripleEquals = (moduleName == null);
217         if (_tripleEquals) {
218             final Module module = findModuleByNamespace(namespace, schemaContext);
219             boolean _tripleEquals_1 = (module == null);
220             if (_tripleEquals_1) {
221                 return null;
222             }
223             String _name = module.getName();
224             moduleName = _name;
225             this.uriToModuleName.put(namespace, moduleName);
226         }
227         return moduleName;
228     }
229
230     public static Set<Class<? extends RpcService>> rpcServicesFromInputStream(InputStream inputStream, BindingIndependentMappingService mappingService){
231         try {
232             DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance();
233             documentBuilder.setNamespaceAware(true);
234             DocumentBuilder builder = documentBuilder.newDocumentBuilder();
235             Document doc = builder.parse(inputStream);
236             Element rootElement = doc.getDocumentElement();
237
238             List<Node<?>> domNodes = XmlDocumentUtils.toDomNodes(rootElement, Optional.<Set<DataSchemaNode>>absent());
239
240             Set<Class<? extends RpcService>> rpcServices = new HashSet<Class<? extends RpcService>>();
241             for (Node<?> node:domNodes){
242                 rpcServices.add(mappingService.getRpcServiceClassFor(node.getNodeType().getNamespace().toString(),node.getNodeType().getRevision().toString()).get());
243             }
244
245             return rpcServices;
246         } catch (ParserConfigurationException e) {
247             logger.trace("Parse configuration exception {}",e);
248         } catch (SAXException e) {
249             logger.trace("SAX exception {}",e);
250         } catch (IOException e) {
251             logger.trace("IOException {}",e);
252         }
253         return null;
254     }
255     public static DataObject dataObjectFromInputStream(org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> path, InputStream inputStream, SchemaContext schemaContext, BindingIndependentMappingService mappingService, DataSchemaNode dataSchema) {
256         // Parse stream into w3c Document
257         try {
258             DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance();
259             documentBuilder.setNamespaceAware(true);
260             DocumentBuilder builder = documentBuilder.newDocumentBuilder();
261             Document doc = builder.parse(inputStream);
262             Element rootElement = doc.getDocumentElement();
263             Node<?> domNode =  XmlDocumentUtils.toDomNode(rootElement, Optional.of(dataSchema), Optional.<XmlCodecProvider>absent());
264             DataObject  dataObject = mappingService.dataObjectFromDataDom(path, (CompositeNode) domNode); //getDataFromResponse
265             return dataObject;
266         } catch (DeserializationException e) {
267
268
269         } catch (ParserConfigurationException e) {
270             logger.trace("Parse configuration exception {}",e);
271         } catch (SAXException e) {
272             logger.trace("SAX exception {}", e);
273         } catch (IOException e) {
274             logger.trace("IOException {}", e);
275         }
276         return null;
277     }
278
279 }