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