QtRestClient  3.0.0
A library for generic JSON-based REST-APIs, with a mechanism to map JSON to Qt objects
restreplyawaitable.h
1 #ifndef RESTREPLYAWAITABLE_H
2 #define RESTREPLYAWAITABLE_H
3 
4 #include "QtRestClient/qtrestclient_global.h"
5 #include "QtRestClient/restreply.h"
6 
7 #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
8 #include "QtRestClient/genericrestreply.h"
9 #endif
10 
11 #if defined(DOXYGEN_RUN) || (!defined(QT_NO_EXCEPTIONS) && QT_CONFIG(future))
12 #include <QtCore/QException>
13 namespace QtRestClient {
16 }
17 #else
18 #include <exception>
19 namespace QtRestClient {
20 using ExceptionBase = std::exception;
21 }
22 #endif
23 
24 namespace QtRestClient {
25 
27 class Q_RESTCLIENT_EXPORT AwaitedException : public ExceptionBase
28 {
29 public:
31  AwaitedException(int code, RestReply::Error type, QVariant data);
32 
34  int errorCode() const;
36  RestReply::Error errorType() const;
38  QVariant errorData() const;
39 
41  QVariantMap errorObject() const;
43  QVariantList errorArray() const;
45  QString errorString() const;
47  QString errorString(const std::function<QString(QVariantMap, int)> &failureTransformer) const;
49  QString errorString(const std::function<QString(QVariantList, int)> &failureTransformer) const;
50 
52  const char *what() const noexcept override;
53 
55  virtual Q_NORETURN void raise() const;
57  virtual ExceptionBase *clone() const;
58 
59 protected:
61  const int _code;
63  const RestReply::Error _type;
65  const QVariant _data;
67  mutable QByteArray _msg;
68 };
69 
70 class RestReplyAwaitablePrivate;
72 class Q_RESTCLIENT_EXPORT RestReplyAwaitable
73 {
74 public:
78  RestReplyAwaitable(RestReplyAwaitable &&other) noexcept;
80  RestReplyAwaitable &operator=(RestReplyAwaitable &&other) noexcept;
82 
88  void prepare(const std::function<void()> &resume);
90  type result();
91 
92 private:
94 };
95 
96 
97 
98 #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
99 template <typename ErrorClassType = QObject*>
102 {
103 public:
105  GenericAwaitedException(int code, const ErrorClassType &data);
107  GenericAwaitedException(int code, RestReply::Error type, const QString &data);
108 
110  ErrorClassType genericError() const;
113  QString errorString(const std::function<QString(ErrorClassType, int)> &failureTransformer) const;
114 
115  Q_NORETURN void raise() const override;
116  ExceptionBase *clone() const override;
117 
118 private:
121 };
122 
124 template <typename DataClassType, typename ErrorClassType = QObject*>
126 {
127 public:
134 
136  using type = DataClassType;
140  void prepare(const std::function<void()> &resume);
142  type result();
143 
144 private:
146  DataClassType successResult;
147  QScopedPointer<exceptionType> errorResult;
148 };
149 
151 template <typename ErrorClassType>
152 class GenericRestReplyAwaitable<void, ErrorClassType>
153 {
154 public:
161 
163  using type = void;
167  void prepare(const std::function<void()> &resume);
169  type result();
170 
171 private:
173  QScopedPointer<exceptionType> errorResult;
174 };
175 #endif
176 
177 // ------------- Generic Implementation -------------
178 
179 #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
180 template<typename DataClassType, typename ErrorClassType>
182  reply{reply}
183 {}
184 
185 template<typename DataClassType, typename ErrorClassType>
187  reply{other.reply},
188  successResult{std::move(other.successResult)}
189 {
190  errorResult.swap(other.errorResult);
191 }
192 
193 template<typename DataClassType, typename ErrorClassType>
195 {
196  reply = other.reply;
197  successResult = std::move(other.successResult);
198  errorResult.swap(other.errorResult);
199  return *this;
200 }
201 
202 template<typename DataClassType, typename ErrorClassType>
204 {
205  reply->onSucceeded([this, resume](int, DataClassType data) {
206  errorResult.reset();
207  successResult = std::move(data);
208  resume();
209  });
210  reply->onFailed([this, resume](int code, ErrorClassType data) {
211  errorResult.reset(new exceptionType{code, std::move(data)});
212  resume();
213  });
214  reply->onSerializeException([this, resume](const QtJsonSerializer::Exception &data) {
215  errorResult.reset(new exceptionType{0, RestReply::Error::Deserialization, QString::fromUtf8(data.what())});
216  resume();
217  });
218  reply->onError([this, resume](const QString &message, int code, RestReply::Error type) {
219  errorResult.reset(new exceptionType{code, type, message});
220  resume();
221  });
222 }
223 
224 template<typename DataClassType, typename ErrorClassType>
226 {
227  if (errorResult) {
228  errorResult->raise();
229  Q_UNREACHABLE();
230  } else
231  return successResult;
232 }
233 
234 
235 
236 template<typename ErrorClassType>
238  reply{reply}
239 {}
240 
241 template<typename ErrorClassType>
243  reply{other.reply}
244 {
245  errorResult.swap(other.errorResult);
246 }
247 
248 template<typename ErrorClassType>
250 {
251  reply = other.reply;
252  errorResult.swap(other.errorResult);
253  return *this;
254 }
255 
256 template<typename ErrorClassType>
257 void GenericRestReplyAwaitable<void, ErrorClassType>::prepare(const std::function<void ()> &resume)
258 {
259  reply->onSucceeded([this, resume](int) {
260  errorResult.reset();
261  resume();
262  });
263  reply->onFailed([this, resume](int code, ErrorClassType data) {
264  errorResult.reset(new exceptionType{code, std::move(data)});
265  resume();
266  });
267  reply->onSerializeException([this, resume](const QtJsonSerializer::Exception &data) {
268  errorResult.reset(new exceptionType{0, RestReply::Error::Deserialization, QString::fromUtf8(data.what())});
269  resume();
270  });
271  reply->onError([this, resume](const QString &message, int code, RestReply::Error type) {
272  errorResult.reset(new exceptionType{code, type, message});
273  resume();
274  });
275 }
276 
277 template<typename ErrorClassType>
279 {
280  if (errorResult) {
281  errorResult->raise();
282  Q_UNREACHABLE();
283  }
284 }
285 
286 
287 
288 template<typename ErrorClassType>
290  AwaitedException{code, RestReply::Error::Failure, QVariant::fromValue<ErrorClassType>(data)}
291 {}
292 
293 template<typename ErrorClassType>
295  AwaitedException{code, type, data}
296 {}
297 
298 template<typename ErrorClassType>
300 {
301  return _data.template value<ErrorClassType>();
302 }
303 
304 template<typename ErrorClassType>
305 QString GenericAwaitedException<ErrorClassType>::errorString(const std::function<QString (ErrorClassType, int)> &failureTransformer) const
306 {
307  if(_type == RestReply::Error::Failure)
308  return failureTransformer(genericError(), _code);
309  else
310  return errorString();
311 }
312 
313 template<typename ErrorClassType>
315 {
316  throw *this;
317 }
318 
319 template<typename ErrorClassType>
321 {
322  return new GenericAwaitedException<ErrorClassType>{*this};
323 }
324 
325 // await method implementations
326 
327 template<typename DataClassType, typename ErrorClassType>
329 {
330  return GenericRestReplyAwaitable<DataClassType, ErrorClassType>{static_cast<TInstance*>(this)};
331 }
332 #endif
333 
334 }
335 
336 #endif // RESTREPLYAWAITABLE_H
QtRestClient::GenericAwaitedException::raise
Q_NORETURN void raise() const override
Inherits QException::raise.
Definition: restreplyawaitable.h:314
QPointer
QtRestClient::AwaitedException::errorObject
QVariantMap errorObject() const
Converts the error data to a map and returns it.
QtJsonSerializer::Exception::what
const char * what() const noexcept final
QtRestClient::GenericRestReplyAwaitable::operator=
GenericRestReplyAwaitable & operator=(GenericRestReplyAwaitable< DataClassType, ErrorClassType > &&other) noexcept
Move assignment operator.
Definition: restreplyawaitable.h:194
QtRestClient::GenericRestReplyAwaitable< void, ErrorClassType >::type
void type
Type returned when awaiting this class.
Definition: restreplyawaitable.h:163
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QtRestClient
The Namespace containing all classes of the QtRestClient module.
Definition: genericrestreply.h:14
QtRestClient::RestReplyAwaitable::type
RestReply::DataType type
Type returned when awaiting this class.
Definition: restreplyawaitable.h:84
QtRestClient::RestReply::Error
Error
Defines the different possible error types.
Definition: restreply.h:45
QtRestClient::GenericRestReplyAwaitable::prepare
void prepare(const std::function< void()> &resume)
Prepare the awaitable for resumption.
Definition: restreplyawaitable.h:203
QtRestClient::GenericRestReplyAwaitable::result
type result()
Extract the result from the awaitable.
Definition: restreplyawaitable.h:225
QtRestClient::GenericAwaitedException
An exception that is throw on errors when awaiting a GenericRestReply.
Definition: restreplyawaitable.h:101
QtRestClient::GenericRestReplyAwaitable::GenericRestReplyAwaitable
GenericRestReplyAwaitable(GenericRestReply< DataClassType, ErrorClassType > *reply)
Construction form a generic rest reply.
Definition: restreplyawaitable.h:181
QtRestClient::GenericRestReplyAwaitable
A helper class to be used with QtCoroutines to await a generic rest reply.
Definition: genericrestreply.h:17
QtRestClient::AwaitedException::errorString
QString errorString() const
Converts the error data to a string and returns it.
QtRestClient::RestReply::Error::Failure
Indicates that the server sent a failure for the request.
QtRestClient::GenericRestReply< void, ErrorClassType >::onSucceeded
GenericRestReply< void, ErrorClassType > * onSucceeded(std::function< void(int)> handler)
Set a handler to be called if the request succeeded.
Definition: genericrestreply.h:361
QtRestClient::GenericRestReplyBase::awaitable
GenericRestReplyAwaitable< DataClassType, ErrorClassType > awaitable()
Returns an awaitable object for this reply.
Definition: restreplyawaitable.h:328
QtRestClient::GenericRestReplyAwaitable::type
DataClassType type
Type returned when awaiting this class.
Definition: restreplyawaitable.h:136
QtRestClient::GenericAwaitedException::GenericAwaitedException
GenericAwaitedException(int code, const ErrorClassType &data)
Constructor, takes an error code, type and additional data.
Definition: restreplyawaitable.h:289
QString
QtRestClient::GenericRestReplyBase::onError
TInstance * onError(std::function< void(QString, int, Error)> handler)
Set a handler to be called if a network error or json parse error occures.
Definition: genericrestreply.h:253
QtRestClient::RestReplyAwaitable
A helper class to be used with QtCoroutines to await a rest reply.
Definition: restreplyawaitable.h:72
QtRestClient::GenericRestReply
A class to handle generic replies for generic requests.
Definition: genericrestreply.h:20
QtRestClient::GenericRestReplyAwaitable< void, ErrorClassType >
A helper class to be used with QtCoroutines to await a generic rest reply.
Definition: restreplyawaitable.h:152
QScopedPointer< RestReplyAwaitablePrivate >
QtRestClient::GenericAwaitedException::genericError
ErrorClassType genericError() const
Returns the additional error data.
Definition: restreplyawaitable.h:299
QtRestClient::RestReply::Error::Deserialization
Indicates that deserializing the received data to the target object failed. Generic replies only!
QtRestClient::AwaitedException::errorArray
QVariantList errorArray() const
Converts the error data to a list and returns it.
QException
QtRestClient::GenericRestReplyBase::onFailed
TInstance * onFailed(std::function< void(int, ErrorClassType)> handler)
Set a handler to be called if the request failed.
Definition: genericrestreply.h:182
QtRestClient::GenericAwaitedException::clone
ExceptionBase * clone() const override
Inherits QException::clone.
Definition: restreplyawaitable.h:320
QtRestClient::RestReply::DataType
std::variant< std::nullopt_t, QCborValue, QJsonValue > DataType
Internal datatype that unites JSON and CBOR data in a typesafe union.
Definition: restreply.h:39
QtRestClient::GenericRestReplyBase::onSerializeException
TInstance * onSerializeException(std::function< void(QtJsonSerializer::Exception &)> handler)
Set a handler to be called on deserialization exceptions.
Definition: genericrestreply.h:210
QtJsonSerializer::Exception
QtRestClient::AwaitedException
An exception that is throw on errors when awaiting a RestReply.
Definition: restreplyawaitable.h:27
QVariant
QtRestClient::RestReply
A class to handle replies for JSON requests.
Definition: restreply.h:23
ExceptionBase
QtRestClient::GenericRestReply< void, ErrorClassType >
A class to handle generic replies for generic requests.
Definition: genericrestreply.h:107
QByteArray