Unity Scopes API
JsonAsyncReader.h
1 /*
2  * Copyright (C) 2014 Canonical Ltd
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 3 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
17  */
18 
19 #pragma once
20 
21 #ifndef _ENABLE_QT_EXPERIMENTAL_
22 #error You should define _ENABLE_QT_EXPERIMENTAL_ in order to use this experimental header file.
23 #endif
24 
25 #include <unity/scopes/qt/HttpAsyncReader.h>
26 #include <unity/util/DefinesPtrs.h>
27 #include <unity/util/NonCopyable.h>
28 
29 #include <QtCore/QJsonArray>
30 #include <QtCore/QJsonDocument>
31 #include <QtCore/QJsonObject>
32 #include <QtCore/QStringList>
33 #include <QtCore/QVector>
34 
35 #include <memory>
36 #include <future>
37 
38 namespace unity
39 {
40 
41 namespace scopes
42 {
43 
44 namespace qt
45 {
46 
48 template <typename TYPE>
49 using ResultsList = std::deque<std::shared_ptr<TYPE>>;
50 
51 template <typename B, typename T>
52 static bool get_results_json(QJsonDocument& json,
53  std::string const& object_name,
54  ResultsList<B>& results,
55  std::string&);
57 
68 {
69 public:
71  NONCOPYABLE(JsonAsyncReader);
72  UNITY_DEFINES_PTRS(JsonAsyncReader);
73 
77  template <typename B>
78  using ParseFunc =
79  std::function<bool(QJsonDocument& root, const std::string&, std::deque<std::shared_ptr<B>>&, std::string&)>;
80 
84  template <typename T>
85  using ResultsFuture = std::future<std::deque<std::shared_ptr<T>>>;
86 
90  template <typename TYPE>
91  using ResultsList = std::deque<std::shared_ptr<TYPE>>;
92 
96  typedef std::future<std::shared_ptr<QJsonDocument>> JsonDocumentFuture;
97 
101  typedef std::shared_ptr<QJsonDocument> QJsonDocumentSptr;
102 
106  typedef std::vector<std::pair<std::string, std::string>> JsonParameters;
107 
108  JsonAsyncReader();
109  virtual ~JsonAsyncReader() = default;
111 
134  template <typename BASE, typename TYPE>
135  ResultsFuture<BASE> async_get(std::string const& uri,
136  std::string const& object_name,
137  ParseFunc<BASE> const& parse = get_results_json<BASE, TYPE>) const;
138 
156  template <typename T>
157  ResultsFuture<T> async_get(std::string const& uri,
158  std::string const& object_name,
159  ParseFunc<T> const& parse = get_results_json<T, T>) const;
160 
184  template <typename BASE, typename TYPE>
185  ResultsFuture<BASE> async_get(std::string const& host,
186  JsonParameters const& params,
187  std::string const& object_name,
188  ParseFunc<BASE> const& parse = get_results_json<BASE, TYPE>) const;
189 
211  template <typename T>
212  ResultsFuture<T> async_get(std::string const& host,
213  JsonParameters const& params,
214  std::string const& object_name,
215  ParseFunc<T> const& parse = get_results_json<T, T>) const;
216 
227  JsonDocumentFuture async_get_parser(std::string const& uri) const;
228 
240  JsonDocumentFuture async_get_parser(std::string const& host, JsonParameters const& params) const;
241 
242 protected:
251  static QJsonDocumentSptr create_parser_with_data(std::string const& data, std::string& error);
252 
254  std::shared_ptr<HttpAsyncReader> p_;
256 };
257 
259 template <typename BASE, typename TYPE>
260 JsonAsyncReader::ResultsFuture<BASE> JsonAsyncReader::async_get(std::string const& uri,
261  std::string const& object_name,
262  ParseFunc<BASE> const& parse) const
263 {
264  return p_->async_get<BASE, TYPE, QJsonDocument>(uri, object_name, JsonAsyncReader::create_parser_with_data, parse);
265 }
266 
267 template <typename T>
268 JsonAsyncReader::ResultsFuture<T> JsonAsyncReader::async_get(std::string const& uri,
269  std::string const& object_name,
270  ParseFunc<T> const& parse) const
271 {
272  return p_->async_get<T, T, QJsonDocument>(uri, object_name, JsonAsyncReader::create_parser_with_data, parse);
273 }
274 
275 template <typename BASE, typename TYPE>
276 JsonAsyncReader::ResultsFuture<BASE> JsonAsyncReader::async_get(std::string const& host,
277  JsonParameters const& params,
278  std::string const& object_name,
279  ParseFunc<BASE> const& parse) const
280 {
281  std::string uri = p_->get_uri(host, params);
282  return p_->async_get<BASE, TYPE, QJsonDocument>(uri, object_name, JsonAsyncReader::create_parser_with_data, parse);
283 }
284 
285 template <typename T>
286 JsonAsyncReader::ResultsFuture<T> JsonAsyncReader::async_get(std::string const& host,
287  JsonParameters const& params,
288  std::string const& object_name,
289  ParseFunc<T> const& parse) const
290 {
291  std::string uri = p_->get_uri(host, params);
292  return p_->async_get<T, T, QJsonDocument>(uri, object_name, JsonAsyncReader::create_parser_with_data, parse);
293 }
294 
295 template <typename B, typename T>
296 static bool get_results_json_object(QJsonObject& root,
297  const std::string& object_name,
298  JsonAsyncReader::ResultsList<B>& results,
299  std::string& error_string)
300 {
301  QString qobject_name(object_name.c_str());
302  if (root.contains(qobject_name))
303  {
304  if (root[qobject_name].isArray())
305  {
306  auto sub_root = root[qobject_name];
307  QJsonArray levelArray = sub_root.toArray();
308  for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex)
309  {
310  QJsonObject levelObject = levelArray[levelIndex].toObject();
311  results.emplace_back(std::make_shared<T>(levelObject));
312  }
313  }
314  else if (root[qobject_name].isObject())
315  {
316  auto sub_root = root[qobject_name].toObject();
317  results.emplace_back(std::make_shared<T>(sub_root));
318  }
319  }
320  else
321  {
322  // iterate thow the existing members
323  for (auto member : root.keys())
324  {
325  auto item = root[member];
326  if (item.isObject())
327  {
328  QJsonObject obj = item.toObject();
329  get_results_json_object<B, T>(obj, object_name, results, error_string);
330  }
331  }
332  }
333  return true;
334 }
335 
336 template <typename B, typename T>
337 static bool get_results_json(QJsonDocument& doc,
338  const std::string& object_name,
339  JsonAsyncReader::ResultsList<B>& results,
340  std::string& error_string)
341 {
342  if (doc.isArray())
343  {
344  QJsonArray levelArray = doc.array();
345  for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex)
346  {
347  QJsonObject levelObject = levelArray[levelIndex].toObject();
348  get_results_json_object<B, T>(levelObject, object_name, results, error_string);
349  }
350  }
351  else if (doc.isObject())
352  {
353  QJsonObject levelObject = doc.object();
354  get_results_json_object<B, T>(levelObject, object_name, results, error_string);
355  }
356  return true;
357 }
359 
360 } // namespace qt
361 
362 } // namespace scopes
363 
364 } // namespace unity
Top-level namespace for all things Unity-related.
Definition: Version.h:49
Class that downloads http JSON files asynchronously.
Definition: JsonAsyncReader.h:67