comparison Framework/Toolbox/OrthancApiClient.cpp @ 300:b4abaeb783b1 am-callable-and-promise

messaging refactoring almost complete: works fine in native
author am@osimis.io
date Tue, 18 Sep 2018 15:23:21 +0200
parents 3897f9f28cfa
children 547e1cf7aa7b
comparison
equal deleted inserted replaced
299:3897f9f28cfa 300:b4abaeb783b1
23 #include "MessagingToolbox.h" 23 #include "MessagingToolbox.h"
24 #include <Core/OrthancException.h> 24 #include <Core/OrthancException.h>
25 25
26 namespace OrthancStone { 26 namespace OrthancStone {
27 27
28 struct OrthancApiClient::InternalGetJsonResponseReadyMessage :
29 public IMessage
30 {
31 OrthancApiClient::BaseRequest* request_;
32 Json::Value response_;
33
34 InternalGetJsonResponseReadyMessage(OrthancApiClient::BaseRequest* request,
35 const Json::Value& response)
36 : IMessage(MessageType_OrthancApi_InternalGetJsonResponseReady),
37 request_(request),
38 response_(response)
39 {
40 }
41
42 };
43
44 struct OrthancApiClient::InternalGetJsonResponseErrorMessage :
45 public IMessage
46 {
47 OrthancApiClient::BaseRequest* request_;
48
49 InternalGetJsonResponseErrorMessage(OrthancApiClient::BaseRequest* request)
50 : IMessage(MessageType_OrthancApi_InternalGetJsonResponseError),
51 request_(request)
52 {
53 }
54 };
55
56
57 // this class handles a single request to the OrthancApiClient.
58 // Once the response is ready, it will emit a message to the responseObserver
59 // the responseObserver must handle only that message (and not all messages from the OrthancApiClient)
60 class OrthancApiClient::BaseRequest:
61 // public IObserver,
62 public IObservable,
63 public Orthanc::IDynamicObject
64 {
65 public:
66 std::string uri_;
67 OrthancApiClient& orthanc_;
68 MessageType messageToEmitWhenResponseReady_;
69 OrthancApiClient::Mode mode_;
70
71 public:
72 BaseRequest(
73 OrthancApiClient& orthanc,
74 IObserver& responseObserver,
75 const std::string& uri,
76 MessageType messageToEmitWhenResponseReady,
77 OrthancApiClient::Mode mode)
78 :
79 //IObserver(orthanc.broker_),
80 IObservable(orthanc.broker_),
81 uri_(uri),
82 orthanc_(orthanc),
83 messageToEmitWhenResponseReady_(messageToEmitWhenResponseReady),
84 mode_(mode)
85 {
86 // this object will emit only a single message, the one the final responseObserver is expecting
87 DeclareEmittableMessage(messageToEmitWhenResponseReady);
88
89 // // this object is observing the OrthancApi so it must handle all messages
90 // DeclareHandledMessage(MessageType_OrthancApi_InternalGetJsonResponseReady);
91 // DeclareIgnoredMessage(MessageType_OrthancApi_InternalGetJsonResponseError);
92
93 //orthanc_.RegisterObserver(*this);
94 //this->RegisterObserver(responseObserver);
95 }
96 virtual ~BaseRequest() {}
97
98 // // mainly maps OrthancApi internal messages to a message that is expected by the responseObserver
99 // virtual void HandleMessage(IObservable& from, const IMessage& message)
100 // {
101 // switch (message.GetType())
102 // {
103 // case MessageType_OrthancApi_InternalGetJsonResponseReady:
104 // {
105 // const OrthancApiClient::InternalGetJsonResponseReadyMessage& messageReceived = dynamic_cast<const OrthancApiClient::InternalGetJsonResponseReadyMessage&>(message);
106 // EmitMessage(OrthancApiClient::GetJsonResponseReadyMessage(messageToEmitWhenResponseReady_, messageReceived.request_->uri_, messageReceived.response_));
107 // orthanc_.ReleaseRequest(messageReceived.request_);
108 // }; break;
109 // default:
110 // throw MessageNotDeclaredException(message.GetType());
111 // }
112 // }
113
114 };
115
116
117 class OrthancApiClient::WebCallback : public IWebService::ICallback
118 {
119 private:
120 OrthancApiClient& that_;
121
122 public:
123 WebCallback(MessageBroker& broker, OrthancApiClient& that) :
124 IWebService::ICallback(broker),
125 that_(that)
126 {
127 }
128
129 virtual void OnHttpRequestSuccess(const std::string& uri,
130 const void* answer,
131 size_t answerSize,
132 Orthanc::IDynamicObject* payload)
133 {
134 OrthancApiClient::BaseRequest* request = dynamic_cast<OrthancApiClient::BaseRequest*>(payload); // the BaseRequests objects belongs to the OrthancApiClient and is deleted in ReleaseRequest when it has been "consumed"
135
136 switch (request->mode_)
137 {
138 case OrthancApiClient::Mode_GetJson:
139 {
140 Json::Value response;
141 if (MessagingToolbox::ParseJson(response, answer, answerSize))
142 {
143 request->EmitMessage(OrthancApiClient::GetJsonResponseReadyMessage(request->messageToEmitWhenResponseReady_, request->uri_, response));
144 }
145 else
146 {
147 // OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
148 // that_.EmitMessage(msg);
149 }
150 }; break;
151
152 default:
153 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
154 }
155 that_.ReleaseRequest(request);
156 }
157
158 virtual void OnHttpRequestError(const std::string& uri,
159 Orthanc::IDynamicObject* payload)
160 {
161 OrthancApiClient::BaseRequest* request = dynamic_cast<OrthancApiClient::BaseRequest*>(payload); // the BaseRequests objects belongs to the OrthancApiClient and is deleted in ReleaseRequest when it has been "consumed"
162
163 switch (request->mode_)
164 {
165 case OrthancApiClient::Mode_GetJson:
166 {
167 // OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
168 // that_.EmitMessage(msg);
169 // TODO: the request shall send an error message
170 }; break;
171
172 default:
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
174 }
175 that_.ReleaseRequest(request);
176 }
177 };
178
179 OrthancApiClient::OrthancApiClient(MessageBroker &broker, IWebService &orthanc) 28 OrthancApiClient::OrthancApiClient(MessageBroker &broker, IWebService &orthanc)
180 : IObservable(broker), 29 : IObservable(broker),
181 orthanc_(orthanc), 30 orthanc_(orthanc)
182 webCallback_(new OrthancApiClient::WebCallback(broker, *this))
183 { 31 {
184 DeclareEmittableMessage(MessageType_OrthancApi_InternalGetJsonResponseReady);
185 DeclareEmittableMessage(MessageType_OrthancApi_InternalGetJsonResponseError);
186 }
187
188 void OrthancApiClient::ScheduleGetJsonRequest(IObserver &responseObserver, const std::string &uri, MessageType messageToEmitWhenResponseReady)
189 {
190 OrthancApiClient::BaseRequest* request = new OrthancApiClient::BaseRequest(*this,
191 responseObserver,
192 uri,
193 messageToEmitWhenResponseReady,
194 OrthancApiClient::Mode_GetJson);
195 orthanc_.ScheduleGetRequest(*webCallback_, uri, IWebService::Headers(), request);
196 requestsInProgress_.insert(request);
197 }
198
199 void OrthancApiClient::ReleaseRequest(BaseRequest* request)
200 {
201 requestsInProgress_.erase(request);
202 delete request;
203 } 32 }
204 33
205 // performs the translation between IWebService messages and OrthancApiClient messages 34 // performs the translation between IWebService messages and OrthancApiClient messages
206 // TODO: handle destruction of this object (with shared_ptr ?::delete_later ???) 35 // TODO: handle destruction of this object (with shared_ptr ?::delete_later ???)
207 class HttpResponseToJsonConverter : public IObserver, IObservable 36 class HttpResponseToJsonConverter : public IObserver, IObservable
208 { 37 {
209 std::auto_ptr<MessageHandler<OrthancApiClient::NewGetJsonResponseReadyMessage>> orthancApiSuccessCallback_; 38 std::auto_ptr<MessageHandler<OrthancApiClient::JsonResponseReadyMessage>> orthancApiSuccessCallback_;
210 std::auto_ptr<MessageHandler<OrthancApiClient::NewHttpErrorMessage>> orthancApiFailureCallback_; 39 std::auto_ptr<MessageHandler<OrthancApiClient::HttpErrorMessage>> orthancApiFailureCallback_;
211 public: 40 public:
212 HttpResponseToJsonConverter(MessageBroker& broker, 41 HttpResponseToJsonConverter(MessageBroker& broker,
213 MessageHandler<OrthancApiClient::NewGetJsonResponseReadyMessage>* orthancApiSuccessCallback, 42 MessageHandler<OrthancApiClient::JsonResponseReadyMessage>* orthancApiSuccessCallback,
214 MessageHandler<OrthancApiClient::NewHttpErrorMessage>* orthancApiFailureCallback) 43 MessageHandler<OrthancApiClient::HttpErrorMessage>* orthancApiFailureCallback)
215 : IObserver(broker), 44 : IObserver(broker),
216 IObservable(broker), 45 IObservable(broker),
217 orthancApiSuccessCallback_(orthancApiSuccessCallback), 46 orthancApiSuccessCallback_(orthancApiSuccessCallback),
218 orthancApiFailureCallback_(orthancApiFailureCallback) 47 orthancApiFailureCallback_(orthancApiFailureCallback)
219 { 48 {
224 Json::Value response; 53 Json::Value response;
225 if (MessagingToolbox::ParseJson(response, message.Answer, message.AnswerSize)) 54 if (MessagingToolbox::ParseJson(response, message.Answer, message.AnswerSize))
226 { 55 {
227 if (orthancApiSuccessCallback_.get() != NULL) 56 if (orthancApiSuccessCallback_.get() != NULL)
228 { 57 {
229 orthancApiSuccessCallback_->Apply(OrthancApiClient::NewGetJsonResponseReadyMessage(message.Uri, response)); 58 orthancApiSuccessCallback_->Apply(OrthancApiClient::JsonResponseReadyMessage(message.Uri, response, message.Payload));
230 } 59 }
231 } 60 }
232 else if (orthancApiFailureCallback_.get() != NULL) 61 else if (orthancApiFailureCallback_.get() != NULL)
233 { 62 {
234 orthancApiFailureCallback_->Apply(OrthancApiClient::NewHttpErrorMessage(message.Uri)); 63 orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.Uri, message.Payload));
235 } 64 }
236 65
237 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) 66 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
238 } 67 }
239 68
240 void ConvertError(const IWebService::NewHttpRequestErrorMessage& message) 69 void ConvertError(const IWebService::NewHttpRequestErrorMessage& message)
241 { 70 {
242 if (orthancApiFailureCallback_.get() != NULL) 71 if (orthancApiFailureCallback_.get() != NULL)
243 { 72 {
244 orthancApiFailureCallback_->Apply(OrthancApiClient::NewHttpErrorMessage(message.Uri)); 73 orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.Uri));
74 }
75
76 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
77 }
78 };
79
80 // performs the translation between IWebService messages and OrthancApiClient messages
81 // TODO: handle destruction of this object (with shared_ptr ?::delete_later ???)
82 class HttpResponseToBinaryConverter : public IObserver, IObservable
83 {
84 std::auto_ptr<MessageHandler<OrthancApiClient::BinaryResponseReadyMessage>> orthancApiSuccessCallback_;
85 std::auto_ptr<MessageHandler<OrthancApiClient::HttpErrorMessage>> orthancApiFailureCallback_;
86 public:
87 HttpResponseToBinaryConverter(MessageBroker& broker,
88 MessageHandler<OrthancApiClient::BinaryResponseReadyMessage>* orthancApiSuccessCallback,
89 MessageHandler<OrthancApiClient::HttpErrorMessage>* orthancApiFailureCallback)
90 : IObserver(broker),
91 IObservable(broker),
92 orthancApiSuccessCallback_(orthancApiSuccessCallback),
93 orthancApiFailureCallback_(orthancApiFailureCallback)
94 {
95 }
96
97 void ConvertResponseToBinary(const IWebService::NewHttpRequestSuccessMessage& message)
98 {
99 if (orthancApiSuccessCallback_.get() != NULL)
100 {
101 orthancApiSuccessCallback_->Apply(OrthancApiClient::BinaryResponseReadyMessage(message.Uri, message.Answer, message.AnswerSize, message.Payload));
102 }
103 else if (orthancApiFailureCallback_.get() != NULL)
104 {
105 orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.Uri, message.Payload));
106 }
107
108 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
109 }
110
111 void ConvertError(const IWebService::NewHttpRequestErrorMessage& message)
112 {
113 if (orthancApiFailureCallback_.get() != NULL)
114 {
115 orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.Uri));
245 } 116 }
246 117
247 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) 118 delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
248 } 119 }
249 }; 120 };
250 121
251 void OrthancApiClient::GetJsonAsync(const std::string& uri, 122 void OrthancApiClient::GetJsonAsync(const std::string& uri,
252 MessageHandler<NewGetJsonResponseReadyMessage>* successCallback, 123 MessageHandler<JsonResponseReadyMessage>* successCallback,
253 MessageHandler<NewHttpErrorMessage>* failureCallback) 124 MessageHandler<HttpErrorMessage>* failureCallback,
125 Orthanc::IDynamicObject* payload)
254 { 126 {
255 HttpResponseToJsonConverter* converter = new HttpResponseToJsonConverter(broker_, successCallback, failureCallback); 127 HttpResponseToJsonConverter* converter = new HttpResponseToJsonConverter(broker_, successCallback, failureCallback); // it is currently deleting itself after being used
256 orthanc_.GetAsync(uri, IWebService::Headers(), NULL, 128 orthanc_.GetAsync(uri, IWebService::Headers(), payload,
257 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestSuccessMessage>(*converter, &HttpResponseToJsonConverter::ConvertResponseToJson), 129 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestSuccessMessage>(*converter, &HttpResponseToJsonConverter::ConvertResponseToJson),
258 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestErrorMessage>(*converter, &HttpResponseToJsonConverter::ConvertError)); 130 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestErrorMessage>(*converter, &HttpResponseToJsonConverter::ConvertError));
259 131
260 } 132 }
261 133
134 void OrthancApiClient::GetBinaryAsync(const std::string& uri,
135 const IWebService::Headers& headers,
136 MessageHandler<BinaryResponseReadyMessage>* successCallback,
137 MessageHandler<HttpErrorMessage>* failureCallback,
138 Orthanc::IDynamicObject* payload)
139 {
140 HttpResponseToBinaryConverter* converter = new HttpResponseToBinaryConverter(broker_, successCallback, failureCallback); // it is currently deleting itself after being used
141 orthanc_.GetAsync(uri, headers, payload,
142 new Callable<HttpResponseToBinaryConverter, IWebService::NewHttpRequestSuccessMessage>(*converter, &HttpResponseToBinaryConverter::ConvertResponseToBinary),
143 new Callable<HttpResponseToBinaryConverter, IWebService::NewHttpRequestErrorMessage>(*converter, &HttpResponseToBinaryConverter::ConvertError));
144 }
145
146 void OrthancApiClient::PostBinaryAsyncExpectJson(const std::string& uri,
147 const std::string& body,
148 MessageHandler<JsonResponseReadyMessage>* successCallback,
149 MessageHandler<HttpErrorMessage>* failureCallback,
150 Orthanc::IDynamicObject* payload)
151 {
152 HttpResponseToJsonConverter* converter = new HttpResponseToJsonConverter(broker_, successCallback, failureCallback); // it is currently deleting itself after being used
153 orthanc_.PostAsync(uri, IWebService::Headers(), body, payload,
154 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestSuccessMessage>(*converter, &HttpResponseToJsonConverter::ConvertResponseToJson),
155 new Callable<HttpResponseToJsonConverter, IWebService::NewHttpRequestErrorMessage>(*converter, &HttpResponseToJsonConverter::ConvertError));
156
157 }
158
159
262 } 160 }