comparison OrthancServer/OrthancRestApi/OrthancRestModalities.cpp @ 1368:b22ba8c5edbe query-retrieve

query retrieve
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 26 May 2015 17:54:34 +0200
parents 6e7e5ed91c2d
children d710ea64f0fd
comparison
equal deleted inserted replaced
1367:fe6e5a9f1ea2 1368:b22ba8c5edbe
37 #include "../../Core/HttpClient.h" 37 #include "../../Core/HttpClient.h"
38 #include "../FromDcmtkBridge.h" 38 #include "../FromDcmtkBridge.h"
39 #include "../Scheduler/ServerJob.h" 39 #include "../Scheduler/ServerJob.h"
40 #include "../Scheduler/StoreScuCommand.h" 40 #include "../Scheduler/StoreScuCommand.h"
41 #include "../Scheduler/StorePeerCommand.h" 41 #include "../Scheduler/StorePeerCommand.h"
42 #include "../QueryRetrieveHandler.h"
43 #include "../ServerToolbox.h"
42 44
43 #include <glog/logging.h> 45 #include <glog/logging.h>
44 46
45 namespace Orthanc 47 namespace Orthanc
46 { 48 {
47 // DICOM SCU ---------------------------------------------------------------- 49 /***************************************************************************
48 50 * DICOM C-Echo SCU
49 static bool MergeQueryAndTemplate(DicomMap& result, 51 ***************************************************************************/
50 const std::string& postData)
51 {
52 Json::Value query;
53 Json::Reader reader;
54
55 if (!reader.parse(postData, query) ||
56 query.type() != Json::objectValue)
57 {
58 return false;
59 }
60
61 Json::Value::Members members = query.getMemberNames();
62 for (size_t i = 0; i < members.size(); i++)
63 {
64 DicomTag t = FromDcmtkBridge::ParseTag(members[i]);
65 result.SetValue(t, query[members[i]].asString());
66 }
67
68 return true;
69 }
70
71 52
72 static void DicomEcho(RestApiPostCall& call) 53 static void DicomEcho(RestApiPostCall& call)
73 { 54 {
74 ServerContext& context = OrthancRestApi::GetContext(call); 55 ServerContext& context = OrthancRestApi::GetContext(call);
75 56
92 // Echo has failed 73 // Echo has failed
93 call.GetOutput().SignalError(HttpStatus_500_InternalServerError); 74 call.GetOutput().SignalError(HttpStatus_500_InternalServerError);
94 } 75 }
95 76
96 77
78
79 /***************************************************************************
80 * DICOM C-Find SCU => DEPRECATED!
81 ***************************************************************************/
82
83 static bool MergeQueryAndTemplate(DicomMap& result,
84 const std::string& postData)
85 {
86 Json::Value query;
87 Json::Reader reader;
88
89 if (!reader.parse(postData, query) ||
90 query.type() != Json::objectValue)
91 {
92 return false;
93 }
94
95 Json::Value::Members members = query.getMemberNames();
96 for (size_t i = 0; i < members.size(); i++)
97 {
98 DicomTag t = FromDcmtkBridge::ParseTag(members[i]);
99 result.SetValue(t, query[members[i]].asString());
100 }
101
102 return true;
103 }
104
105
106 static void FindPatient(DicomFindAnswers& result,
107 DicomUserConnection& connection,
108 const DicomMap& fields)
109 {
110 // Only keep the filters from "fields" that are related to the patient
111 DicomMap s;
112 fields.ExtractPatientInformation(s);
113 connection.Find(result, ResourceType_Patient, s);
114 }
115
116
117 static void FindStudy(DicomFindAnswers& result,
118 DicomUserConnection& connection,
119 const DicomMap& fields)
120 {
121 // Only keep the filters from "fields" that are related to the study
122 DicomMap s;
123 fields.ExtractStudyInformation(s);
124
125 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID);
126 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER);
127 s.CopyTagIfExists(fields, DICOM_TAG_MODALITIES_IN_STUDY);
128
129 connection.Find(result, ResourceType_Study, s);
130 }
131
132 static void FindSeries(DicomFindAnswers& result,
133 DicomUserConnection& connection,
134 const DicomMap& fields)
135 {
136 // Only keep the filters from "fields" that are related to the series
137 DicomMap s;
138 fields.ExtractSeriesInformation(s);
139
140 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID);
141 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER);
142 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID);
143
144 connection.Find(result, ResourceType_Series, s);
145 }
146
147 static void FindInstance(DicomFindAnswers& result,
148 DicomUserConnection& connection,
149 const DicomMap& fields)
150 {
151 // Only keep the filters from "fields" that are related to the instance
152 DicomMap s;
153 fields.ExtractInstanceInformation(s);
154
155 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID);
156 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER);
157 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID);
158 s.CopyTagIfExists(fields, DICOM_TAG_SERIES_INSTANCE_UID);
159
160 connection.Find(result, ResourceType_Instance, s);
161 }
162
163
97 static void DicomFindPatient(RestApiPostCall& call) 164 static void DicomFindPatient(RestApiPostCall& call)
98 { 165 {
99 ServerContext& context = OrthancRestApi::GetContext(call); 166 LOG(WARNING) << "This URI is deprecated: " << call.FlattenUri();
100 167 ServerContext& context = OrthancRestApi::GetContext(call);
101 DicomMap m; 168
102 DicomMap::SetupFindPatientTemplate(m); 169 DicomMap fields;
103 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 170 DicomMap::SetupFindPatientTemplate(fields);
171 if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
104 { 172 {
105 return; 173 return;
106 } 174 }
107 175
108 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", "")); 176 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
109 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote); 177 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote);
110 178
111 DicomFindAnswers answers; 179 DicomFindAnswers answers;
112 locker.GetConnection().FindPatient(answers, m); 180 FindPatient(answers, locker.GetConnection(), fields);
113 181
114 Json::Value result; 182 Json::Value result;
115 answers.ToJson(result); 183 answers.ToJson(result, true);
116 call.GetOutput().AnswerJson(result); 184 call.GetOutput().AnswerJson(result);
117 } 185 }
118 186
119 static void DicomFindStudy(RestApiPostCall& call) 187 static void DicomFindStudy(RestApiPostCall& call)
120 { 188 {
121 ServerContext& context = OrthancRestApi::GetContext(call); 189 LOG(WARNING) << "This URI is deprecated: " << call.FlattenUri();
122 190 ServerContext& context = OrthancRestApi::GetContext(call);
123 DicomMap m; 191
124 DicomMap::SetupFindStudyTemplate(m); 192 DicomMap fields;
125 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 193 DicomMap::SetupFindStudyTemplate(fields);
126 { 194 if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
127 return; 195 {
128 } 196 return;
129 197 }
130 if (m.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 && 198
131 m.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) 199 if (fields.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 &&
200 fields.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2)
132 { 201 {
133 return; 202 return;
134 } 203 }
135 204
136 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", "")); 205 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
137 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote); 206 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote);
138 207
139 DicomFindAnswers answers; 208 DicomFindAnswers answers;
140 locker.GetConnection().FindStudy(answers, m); 209 FindStudy(answers, locker.GetConnection(), fields);
141 210
142 Json::Value result; 211 Json::Value result;
143 answers.ToJson(result); 212 answers.ToJson(result, true);
144 call.GetOutput().AnswerJson(result); 213 call.GetOutput().AnswerJson(result);
145 } 214 }
146 215
147 static void DicomFindSeries(RestApiPostCall& call) 216 static void DicomFindSeries(RestApiPostCall& call)
148 { 217 {
149 ServerContext& context = OrthancRestApi::GetContext(call); 218 LOG(WARNING) << "This URI is deprecated: " << call.FlattenUri();
150 219 ServerContext& context = OrthancRestApi::GetContext(call);
151 DicomMap m; 220
152 DicomMap::SetupFindSeriesTemplate(m); 221 DicomMap fields;
153 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 222 DicomMap::SetupFindSeriesTemplate(fields);
154 { 223 if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
155 return; 224 {
156 } 225 return;
157 226 }
158 if ((m.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 && 227
159 m.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) || 228 if ((fields.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 &&
160 m.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString().size() <= 2) 229 fields.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) ||
230 fields.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString().size() <= 2)
161 { 231 {
162 return; 232 return;
163 } 233 }
164 234
165 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", "")); 235 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
166 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote); 236 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote);
167 237
168 DicomFindAnswers answers; 238 DicomFindAnswers answers;
169 locker.GetConnection().FindSeries(answers, m); 239 FindSeries(answers, locker.GetConnection(), fields);
170 240
171 Json::Value result; 241 Json::Value result;
172 answers.ToJson(result); 242 answers.ToJson(result, true);
173 call.GetOutput().AnswerJson(result); 243 call.GetOutput().AnswerJson(result);
174 } 244 }
175 245
176 static void DicomFindInstance(RestApiPostCall& call) 246 static void DicomFindInstance(RestApiPostCall& call)
177 { 247 {
178 ServerContext& context = OrthancRestApi::GetContext(call); 248 LOG(WARNING) << "This URI is deprecated: " << call.FlattenUri();
179 249 ServerContext& context = OrthancRestApi::GetContext(call);
180 DicomMap m; 250
181 DicomMap::SetupFindInstanceTemplate(m); 251 DicomMap fields;
182 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 252 DicomMap::SetupFindInstanceTemplate(fields);
183 { 253 if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
184 return; 254 {
185 } 255 return;
186 256 }
187 if ((m.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 && 257
188 m.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) || 258 if ((fields.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 &&
189 m.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString().size() <= 2 || 259 fields.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) ||
190 m.GetValue(DICOM_TAG_SERIES_INSTANCE_UID).AsString().size() <= 2) 260 fields.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString().size() <= 2 ||
261 fields.GetValue(DICOM_TAG_SERIES_INSTANCE_UID).AsString().size() <= 2)
191 { 262 {
192 return; 263 return;
193 } 264 }
194 265
195 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", "")); 266 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
196 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote); 267 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote);
197 268
198 DicomFindAnswers answers; 269 DicomFindAnswers answers;
199 locker.GetConnection().FindInstance(answers, m); 270 FindInstance(answers, locker.GetConnection(), fields);
200 271
201 Json::Value result; 272 Json::Value result;
202 answers.ToJson(result); 273 answers.ToJson(result, true);
203 call.GetOutput().AnswerJson(result); 274 call.GetOutput().AnswerJson(result);
204 } 275 }
205 276
277
206 static void DicomFind(RestApiPostCall& call) 278 static void DicomFind(RestApiPostCall& call)
207 { 279 {
280 LOG(WARNING) << "This URI is deprecated: " << call.FlattenUri();
208 ServerContext& context = OrthancRestApi::GetContext(call); 281 ServerContext& context = OrthancRestApi::GetContext(call);
209 282
210 DicomMap m; 283 DicomMap m;
211 DicomMap::SetupFindPatientTemplate(m); 284 DicomMap::SetupFindPatientTemplate(m);
212 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 285 if (!MergeQueryAndTemplate(m, call.GetPostBody()))
216 289
217 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", "")); 290 RemoteModalityParameters remote = Configuration::GetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
218 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote); 291 ReusableDicomUserConnection::Locker locker(context.GetReusableDicomUserConnection(), remote);
219 292
220 DicomFindAnswers patients; 293 DicomFindAnswers patients;
221 locker.GetConnection().FindPatient(patients, m); 294 FindPatient(patients, locker.GetConnection(), m);
222 295
223 // Loop over the found patients 296 // Loop over the found patients
224 Json::Value result = Json::arrayValue; 297 Json::Value result = Json::arrayValue;
225 for (size_t i = 0; i < patients.GetSize(); i++) 298 for (size_t i = 0; i < patients.GetSize(); i++)
226 { 299 {
227 Json::Value patient(Json::objectValue); 300 Json::Value patient(Json::objectValue);
228 FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i)); 301 FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i), true);
229 302
230 DicomMap::SetupFindStudyTemplate(m); 303 DicomMap::SetupFindStudyTemplate(m);
231 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 304 if (!MergeQueryAndTemplate(m, call.GetPostBody()))
232 { 305 {
233 return; 306 return;
234 } 307 }
235 m.CopyTagIfExists(patients.GetAnswer(i), DICOM_TAG_PATIENT_ID); 308 m.CopyTagIfExists(patients.GetAnswer(i), DICOM_TAG_PATIENT_ID);
236 309
237 DicomFindAnswers studies; 310 DicomFindAnswers studies;
238 locker.GetConnection().FindStudy(studies, m); 311 FindStudy(studies, locker.GetConnection(), m);
239 312
240 patient["Studies"] = Json::arrayValue; 313 patient["Studies"] = Json::arrayValue;
241 314
242 // Loop over the found studies 315 // Loop over the found studies
243 for (size_t j = 0; j < studies.GetSize(); j++) 316 for (size_t j = 0; j < studies.GetSize(); j++)
244 { 317 {
245 Json::Value study(Json::objectValue); 318 Json::Value study(Json::objectValue);
246 FromDcmtkBridge::ToJson(study, studies.GetAnswer(j)); 319 FromDcmtkBridge::ToJson(study, studies.GetAnswer(j), true);
247 320
248 DicomMap::SetupFindSeriesTemplate(m); 321 DicomMap::SetupFindSeriesTemplate(m);
249 if (!MergeQueryAndTemplate(m, call.GetPostBody())) 322 if (!MergeQueryAndTemplate(m, call.GetPostBody()))
250 { 323 {
251 return; 324 return;
252 } 325 }
253 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_PATIENT_ID); 326 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_PATIENT_ID);
254 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_STUDY_INSTANCE_UID); 327 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_STUDY_INSTANCE_UID);
255 328
256 DicomFindAnswers series; 329 DicomFindAnswers series;
257 locker.GetConnection().FindSeries(series, m); 330 FindSeries(series, locker.GetConnection(), m);
258 331
259 // Loop over the found series 332 // Loop over the found series
260 study["Series"] = Json::arrayValue; 333 study["Series"] = Json::arrayValue;
261 for (size_t k = 0; k < series.GetSize(); k++) 334 for (size_t k = 0; k < series.GetSize(); k++)
262 { 335 {
263 Json::Value series2(Json::objectValue); 336 Json::Value series2(Json::objectValue);
264 FromDcmtkBridge::ToJson(series2, series.GetAnswer(k)); 337 FromDcmtkBridge::ToJson(series2, series.GetAnswer(k), true);
265 study["Series"].append(series2); 338 study["Series"].append(series2);
266 } 339 }
267 340
268 patient["Studies"].append(study); 341 patient["Studies"].append(study);
269 } 342 }
272 } 345 }
273 346
274 call.GetOutput().AnswerJson(result); 347 call.GetOutput().AnswerJson(result);
275 } 348 }
276 349
350
351
352 /***************************************************************************
353 * DICOM C-Find and C-Move SCU => Recommended since Orthanc 0.9.0
354 ***************************************************************************/
355
356 static void DicomQuery(RestApiPostCall& call)
357 {
358 ServerContext& context = OrthancRestApi::GetContext(call);
359 Json::Value request;
360
361 if (call.ParseJsonRequest(request) &&
362 request.type() == Json::objectValue &&
363 request.isMember("Level") && request["Level"].type() == Json::stringValue &&
364 (!request.isMember("Query") || request["Query"].type() == Json::objectValue))
365 {
366 std::auto_ptr<QueryRetrieveHandler> handler(new QueryRetrieveHandler(context));
367
368 handler->SetModality(call.GetUriComponent("id", ""));
369 handler->SetLevel(StringToResourceType(request["Level"].asString().c_str()));
370
371 if (request.isMember("Query"))
372 {
373 Json::Value::Members tags = request["Query"].getMemberNames();
374 for (size_t i = 0; i < tags.size(); i++)
375 {
376 handler->SetQuery(FromDcmtkBridge::ParseTag(tags[i].c_str()),
377 request["Query"][tags[i]].asString());
378 }
379 }
380
381 handler->Run();
382
383 std::string s = context.GetQueryRetrieveArchive().Add(handler.release());
384 Json::Value result = Json::objectValue;
385 result["ID"] = s;
386 result["Path"] = "/queries/" + s;
387 call.GetOutput().AnswerJson(result);
388 }
389 }
390
391
392 static void ListQueries(RestApiGetCall& call)
393 {
394 ServerContext& context = OrthancRestApi::GetContext(call);
395
396 std::list<std::string> queries;
397 context.GetQueryRetrieveArchive().List(queries);
398
399 Json::Value result = Json::arrayValue;
400 for (std::list<std::string>::const_iterator
401 it = queries.begin(); it != queries.end(); ++it)
402 {
403 result.append(*it);
404 }
405
406 call.GetOutput().AnswerJson(result);
407 }
408
409
410 namespace
411 {
412 class QueryAccessor
413 {
414 private:
415 ServerContext& context_;
416 SharedArchive::Accessor accessor_;
417 QueryRetrieveHandler& handler_;
418
419 public:
420 QueryAccessor(RestApiCall& call) :
421 context_(OrthancRestApi::GetContext(call)),
422 accessor_(context_.GetQueryRetrieveArchive(), call.GetUriComponent("id", "")),
423 handler_(dynamic_cast<QueryRetrieveHandler&>(accessor_.GetItem()))
424 {
425 }
426
427 QueryRetrieveHandler* operator->()
428 {
429 return &handler_;
430 }
431 };
432
433 static void AnswerDicomMap(RestApiCall& call,
434 const DicomMap& value,
435 bool simplify)
436 {
437 Json::Value full = Json::objectValue;
438 FromDcmtkBridge::ToJson(full, value, simplify);
439 call.GetOutput().AnswerJson(full);
440 }
441 }
442
443
444 static void ListQueryAnswers(RestApiGetCall& call)
445 {
446 QueryAccessor query(call);
447 size_t count = query->GetAnswerCount();
448
449 Json::Value result = Json::arrayValue;
450 for (size_t i = 0; i < count; i++)
451 {
452 result.append(boost::lexical_cast<std::string>(i));
453 }
454
455 call.GetOutput().AnswerJson(result);
456 }
457
458
459 static void GetQueryOneAnswer(RestApiGetCall& call)
460 {
461 size_t index = boost::lexical_cast<size_t>(call.GetUriComponent("index", ""));
462 QueryAccessor query(call);
463 AnswerDicomMap(call, query->GetAnswer(index), call.HasArgument("simplify"));
464 }
465
466
467 static void RetrieveOneAnswer(RestApiPostCall& call)
468 {
469 size_t index = boost::lexical_cast<size_t>(call.GetUriComponent("index", ""));
470
471 LOG(WARNING) << "Driving C-Move SCU on modality: " << call.GetPostBody();
472
473 QueryAccessor query(call);
474 query->Retrieve(call.GetPostBody(), index);
475
476 // Retrieve has succeeded
477 call.GetOutput().AnswerBuffer("{}", "application/json");
478 }
479
480
481 static void RetrieveAllAnswers(RestApiPostCall& call)
482 {
483 LOG(WARNING) << "Driving C-Move SCU on modality: " << call.GetPostBody();
484
485 QueryAccessor query(call);
486 query->Retrieve(call.GetPostBody());
487
488 // Retrieve has succeeded
489 call.GetOutput().AnswerBuffer("{}", "application/json");
490 }
491
492
493 static void GetQueryArguments(RestApiGetCall& call)
494 {
495 QueryAccessor query(call);
496 AnswerDicomMap(call, query->GetQuery(), call.HasArgument("simplify"));
497 }
498
499
500 static void GetQueryLevel(RestApiGetCall& call)
501 {
502 QueryAccessor query(call);
503 call.GetOutput().AnswerBuffer(EnumerationToString(query->GetLevel()), "text/plain");
504 }
505
506
507 static void GetQueryModality(RestApiGetCall& call)
508 {
509 QueryAccessor query(call);
510 call.GetOutput().AnswerBuffer(query->GetModalitySymbolicName(), "text/plain");
511 }
512
513
514 static void DeleteQuery(RestApiDeleteCall& call)
515 {
516 ServerContext& context = OrthancRestApi::GetContext(call);
517 context.GetQueryRetrieveArchive().Remove(call.GetUriComponent("id", ""));
518 call.GetOutput().AnswerBuffer("", "text/plain");
519 }
520
521
522 static void ListQueryOperations(RestApiGetCall& call)
523 {
524 // Ensure that the query of interest does exist
525 QueryAccessor query(call);
526
527 RestApi::AutoListChildren(call);
528 }
529
530
531 static void ListQueryAnswerOperations(RestApiGetCall& call)
532 {
533 // Ensure that the query of interest does exist
534 QueryAccessor query(call);
535
536 // Ensure that the answer of interest does exist
537 size_t index = boost::lexical_cast<size_t>(call.GetUriComponent("index", ""));
538 query->GetAnswer(index);
539
540 RestApi::AutoListChildren(call);
541 }
542
543
544
545
546 /***************************************************************************
547 * DICOM C-Store SCU
548 ***************************************************************************/
277 549
278 static bool GetInstancesToExport(std::list<std::string>& instances, 550 static bool GetInstancesToExport(std::list<std::string>& instances,
279 const std::string& remote, 551 const std::string& remote,
280 RestApiPostCall& call) 552 RestApiPostCall& call)
281 { 553 {
377 call.GetOutput().SignalError(HttpStatus_500_InternalServerError); 649 call.GetOutput().SignalError(HttpStatus_500_InternalServerError);
378 } 650 }
379 } 651 }
380 652
381 653
382 // Orthanc Peers ------------------------------------------------------------ 654 /***************************************************************************
655 * Orthanc Peers => Store client
656 ***************************************************************************/
383 657
384 static bool IsExistingPeer(const OrthancRestApi::SetOfStrings& peers, 658 static bool IsExistingPeer(const OrthancRestApi::SetOfStrings& peers,
385 const std::string& id) 659 const std::string& id)
386 { 660 {
387 return peers.find(id) != peers.end(); 661 return peers.find(id) != peers.end();
541 Register("/modalities/{id}/find-series", DicomFindSeries); 815 Register("/modalities/{id}/find-series", DicomFindSeries);
542 Register("/modalities/{id}/find-instance", DicomFindInstance); 816 Register("/modalities/{id}/find-instance", DicomFindInstance);
543 Register("/modalities/{id}/find", DicomFind); 817 Register("/modalities/{id}/find", DicomFind);
544 Register("/modalities/{id}/store", DicomStore); 818 Register("/modalities/{id}/store", DicomStore);
545 819
820 // For Query/Retrieve
821 Register("/modalities/{id}/query", DicomQuery);
822 Register("/queries", ListQueries);
823 Register("/queries/{id}", DeleteQuery);
824 Register("/queries/{id}", ListQueryOperations);
825 Register("/queries/{id}/answers", ListQueryAnswers);
826 Register("/queries/{id}/answers/{index}", ListQueryAnswerOperations);
827 Register("/queries/{id}/answers/{index}/content", GetQueryOneAnswer);
828 Register("/queries/{id}/answers/{index}/retrieve", RetrieveOneAnswer);
829 Register("/queries/{id}/level", GetQueryLevel);
830 Register("/queries/{id}/modality", GetQueryModality);
831 Register("/queries/{id}/query", GetQueryArguments);
832 Register("/queries/{id}/retrieve", RetrieveAllAnswers);
833
546 Register("/peers", ListPeers); 834 Register("/peers", ListPeers);
547 Register("/peers/{id}", ListPeerOperations); 835 Register("/peers/{id}", ListPeerOperations);
548 Register("/peers/{id}", UpdatePeer); 836 Register("/peers/{id}", UpdatePeer);
549 Register("/peers/{id}", DeletePeer); 837 Register("/peers/{id}", DeletePeer);
550 Register("/peers/{id}/store", PeerStore); 838 Register("/peers/{id}/store", PeerStore);