Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 4415:b50410d0e98c
cont openapi
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 28 Dec 2020 15:32:01 +0100 |
parents | d928dfcacb4b |
children | 0b27841950d5 |
comparison
equal
deleted
inserted
replaced
4414:d928dfcacb4b | 4415:b50410d0e98c |
---|---|
65 static Orthanc::Semaphore throttlingSemaphore_(4); // TODO => PARAMETER? | 65 static Orthanc::Semaphore throttlingSemaphore_(4); // TODO => PARAMETER? |
66 | 66 |
67 | 67 |
68 namespace Orthanc | 68 namespace Orthanc |
69 { | 69 { |
70 static void AnswerDicomAsJson(RestApiCall& call, | |
71 const Json::Value& dicom, | |
72 DicomToJsonFormat mode) | |
73 { | |
74 if (mode != DicomToJsonFormat_Full) | |
75 { | |
76 Json::Value simplified; | |
77 Toolbox::SimplifyDicomAsJson(simplified, dicom, mode); | |
78 call.GetOutput().AnswerJson(simplified); | |
79 } | |
80 else | |
81 { | |
82 call.GetOutput().AnswerJson(dicom); | |
83 } | |
84 } | |
85 | |
86 | |
87 static DicomToJsonFormat GetDicomFormat(const RestApiGetCall& call) | |
88 { | |
89 if (call.HasArgument("simplify")) | |
90 { | |
91 return DicomToJsonFormat_Human; | |
92 } | |
93 else if (call.HasArgument("short")) | |
94 { | |
95 return DicomToJsonFormat_Short; | |
96 } | |
97 else | |
98 { | |
99 return DicomToJsonFormat_Full; | |
100 } | |
101 } | |
102 | |
103 | |
104 static void AnswerDicomAsJson(RestApiGetCall& call, | |
105 const Json::Value& dicom) | |
106 { | |
107 AnswerDicomAsJson(call, dicom, GetDicomFormat(call)); | |
108 } | |
109 | |
110 | |
111 static void ParseSetOfTags(std::set<DicomTag>& target, | |
112 const RestApiGetCall& call, | |
113 const std::string& argument) | |
114 { | |
115 target.clear(); | |
116 | |
117 if (call.HasArgument(argument)) | |
118 { | |
119 std::vector<std::string> tags; | |
120 Toolbox::TokenizeString(tags, call.GetArgument(argument, ""), ','); | |
121 | |
122 for (size_t i = 0; i < tags.size(); i++) | |
123 { | |
124 target.insert(FromDcmtkBridge::ParseTag(tags[i])); | |
125 } | |
126 } | |
127 } | |
128 | |
129 | |
130 // List all the patients, studies, series or instances ---------------------- | |
131 | |
132 static void AnswerListOfResources(RestApiOutput& output, | |
133 ServerIndex& index, | |
134 const std::list<std::string>& resources, | |
135 ResourceType level, | |
136 bool expand) | |
137 { | |
138 Json::Value answer = Json::arrayValue; | |
139 | |
140 for (std::list<std::string>::const_iterator | |
141 resource = resources.begin(); resource != resources.end(); ++resource) | |
142 { | |
143 if (expand) | |
144 { | |
145 Json::Value item; | |
146 if (index.LookupResource(item, *resource, level)) | |
147 { | |
148 answer.append(item); | |
149 } | |
150 } | |
151 else | |
152 { | |
153 answer.append(*resource); | |
154 } | |
155 } | |
156 | |
157 output.AnswerJson(answer); | |
158 } | |
159 | |
160 | |
161 template <enum ResourceType resourceType> | |
162 static void ListResources(RestApiGetCall& call) | |
163 { | |
164 if (call.IsDocumentation()) | |
165 { | |
166 const std::string resources = GetResourceTypeText(resourceType, true /* plural */, false /* lower case */); | |
167 call.GetDocumentation() | |
168 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) | |
169 .SetSummary("List the available " + resources) | |
170 .SetDescription("List the Orthanc identifiers of all the available DICOM " + resources) | |
171 .SetHttpGetArgument("limit", RestApiCallDocumentation::Type_Number, "Limit the number of results", false) | |
172 .SetHttpGetArgument("since", RestApiCallDocumentation::Type_Number, "Show only the resources since the provided index", false) | |
173 .SetHttpGetArgument("expand", RestApiCallDocumentation::Type_String, | |
174 "If present, retrieve detailed information about the individual " + resources, false) | |
175 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information " | |
176 "about the reported " + resources + " (if `expand` argument is provided)") | |
177 .SetHttpGetSample("https://demo.orthanc-server.com/" + resources + "?since=0&limit=2", true); | |
178 return; | |
179 } | |
180 | |
181 ServerIndex& index = OrthancRestApi::GetIndex(call); | |
182 | |
183 std::list<std::string> result; | |
184 | |
185 if (call.HasArgument("limit") || | |
186 call.HasArgument("since")) | |
187 { | |
188 if (!call.HasArgument("limit")) | |
189 { | |
190 throw OrthancException(ErrorCode_BadRequest, | |
191 "Missing \"limit\" argument for GET request against: " + | |
192 call.FlattenUri()); | |
193 } | |
194 | |
195 if (!call.HasArgument("since")) | |
196 { | |
197 throw OrthancException(ErrorCode_BadRequest, | |
198 "Missing \"since\" argument for GET request against: " + | |
199 call.FlattenUri()); | |
200 } | |
201 | |
202 size_t since = boost::lexical_cast<size_t>(call.GetArgument("since", "")); | |
203 size_t limit = boost::lexical_cast<size_t>(call.GetArgument("limit", "")); | |
204 index.GetAllUuids(result, resourceType, since, limit); | |
205 } | |
206 else | |
207 { | |
208 index.GetAllUuids(result, resourceType); | |
209 } | |
210 | |
211 | |
212 AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand")); | |
213 } | |
214 | |
215 | |
216 | |
217 static std::string GetDocumentationSampleResource(ResourceType type) | 70 static std::string GetDocumentationSampleResource(ResourceType type) |
218 { | 71 { |
219 switch (type) | 72 switch (type) |
220 { | 73 { |
221 case Orthanc::ResourceType_Instance: | 74 case Orthanc::ResourceType_Instance: |
238 throw OrthancException(ErrorCode_ParameterOutOfRange); | 91 throw OrthancException(ErrorCode_ParameterOutOfRange); |
239 } | 92 } |
240 } | 93 } |
241 | 94 |
242 | 95 |
96 static void AnswerDicomAsJson(RestApiCall& call, | |
97 const Json::Value& dicom, | |
98 DicomToJsonFormat mode) | |
99 { | |
100 if (mode != DicomToJsonFormat_Full) | |
101 { | |
102 Json::Value simplified; | |
103 Toolbox::SimplifyDicomAsJson(simplified, dicom, mode); | |
104 call.GetOutput().AnswerJson(simplified); | |
105 } | |
106 else | |
107 { | |
108 call.GetOutput().AnswerJson(dicom); | |
109 } | |
110 } | |
111 | |
112 | |
113 static DicomToJsonFormat GetDicomFormat(const RestApiGetCall& call) | |
114 { | |
115 if (call.HasArgument("simplify")) | |
116 { | |
117 return DicomToJsonFormat_Human; | |
118 } | |
119 else if (call.HasArgument("short")) | |
120 { | |
121 return DicomToJsonFormat_Short; | |
122 } | |
123 else | |
124 { | |
125 return DicomToJsonFormat_Full; | |
126 } | |
127 } | |
128 | |
129 | |
130 static void AnswerDicomAsJson(RestApiGetCall& call, | |
131 const Json::Value& dicom) | |
132 { | |
133 AnswerDicomAsJson(call, dicom, GetDicomFormat(call)); | |
134 } | |
135 | |
136 | |
137 static void ParseSetOfTags(std::set<DicomTag>& target, | |
138 const RestApiGetCall& call, | |
139 const std::string& argument) | |
140 { | |
141 target.clear(); | |
142 | |
143 if (call.HasArgument(argument)) | |
144 { | |
145 std::vector<std::string> tags; | |
146 Toolbox::TokenizeString(tags, call.GetArgument(argument, ""), ','); | |
147 | |
148 for (size_t i = 0; i < tags.size(); i++) | |
149 { | |
150 target.insert(FromDcmtkBridge::ParseTag(tags[i])); | |
151 } | |
152 } | |
153 } | |
154 | |
155 | |
156 // List all the patients, studies, series or instances ---------------------- | |
157 | |
158 static void AnswerListOfResources(RestApiOutput& output, | |
159 ServerIndex& index, | |
160 const std::list<std::string>& resources, | |
161 ResourceType level, | |
162 bool expand) | |
163 { | |
164 Json::Value answer = Json::arrayValue; | |
165 | |
166 for (std::list<std::string>::const_iterator | |
167 resource = resources.begin(); resource != resources.end(); ++resource) | |
168 { | |
169 if (expand) | |
170 { | |
171 Json::Value item; | |
172 if (index.LookupResource(item, *resource, level)) | |
173 { | |
174 answer.append(item); | |
175 } | |
176 } | |
177 else | |
178 { | |
179 answer.append(*resource); | |
180 } | |
181 } | |
182 | |
183 output.AnswerJson(answer); | |
184 } | |
185 | |
186 | |
187 template <enum ResourceType resourceType> | |
188 static void ListResources(RestApiGetCall& call) | |
189 { | |
190 if (call.IsDocumentation()) | |
191 { | |
192 const std::string resources = GetResourceTypeText(resourceType, true /* plural */, false /* lower case */); | |
193 call.GetDocumentation() | |
194 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) | |
195 .SetSummary("List the available " + resources) | |
196 .SetDescription("List the Orthanc identifiers of all the available DICOM " + resources) | |
197 .SetHttpGetArgument("limit", RestApiCallDocumentation::Type_Number, "Limit the number of results", false) | |
198 .SetHttpGetArgument("since", RestApiCallDocumentation::Type_Number, "Show only the resources since the provided index", false) | |
199 .SetHttpGetArgument("expand", RestApiCallDocumentation::Type_String, | |
200 "If present, retrieve detailed information about the individual " + resources, false) | |
201 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information " | |
202 "about the reported " + resources + " (if `expand` argument is provided)") | |
203 .SetHttpGetSample("https://demo.orthanc-server.com/" + resources + "?since=0&limit=2", true); | |
204 return; | |
205 } | |
206 | |
207 ServerIndex& index = OrthancRestApi::GetIndex(call); | |
208 | |
209 std::list<std::string> result; | |
210 | |
211 if (call.HasArgument("limit") || | |
212 call.HasArgument("since")) | |
213 { | |
214 if (!call.HasArgument("limit")) | |
215 { | |
216 throw OrthancException(ErrorCode_BadRequest, | |
217 "Missing \"limit\" argument for GET request against: " + | |
218 call.FlattenUri()); | |
219 } | |
220 | |
221 if (!call.HasArgument("since")) | |
222 { | |
223 throw OrthancException(ErrorCode_BadRequest, | |
224 "Missing \"since\" argument for GET request against: " + | |
225 call.FlattenUri()); | |
226 } | |
227 | |
228 size_t since = boost::lexical_cast<size_t>(call.GetArgument("since", "")); | |
229 size_t limit = boost::lexical_cast<size_t>(call.GetArgument("limit", "")); | |
230 index.GetAllUuids(result, resourceType, since, limit); | |
231 } | |
232 else | |
233 { | |
234 index.GetAllUuids(result, resourceType); | |
235 } | |
236 | |
237 | |
238 AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand")); | |
239 } | |
240 | |
241 | |
242 | |
243 template <enum ResourceType resourceType> | 243 template <enum ResourceType resourceType> |
244 static void GetSingleResource(RestApiGetCall& call) | 244 static void GetSingleResource(RestApiGetCall& call) |
245 { | 245 { |
246 if (call.IsDocumentation()) | 246 if (call.IsDocumentation()) |
247 { | 247 { |
434 .SetTag("Instances") | 434 .SetTag("Instances") |
435 .SetSummary("Get human-readable tags") | 435 .SetSummary("Get human-readable tags") |
436 .SetDescription("Get the DICOM tags in human-readable format") | 436 .SetDescription("Get the DICOM tags in human-readable format") |
437 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") | 437 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") |
438 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") | 438 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") |
439 .SetHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", true); | 439 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); |
440 return; | 440 return; |
441 } | 441 } |
442 else | 442 else |
443 { | 443 { |
444 throw OrthancException(ErrorCode_NotImplemented); | 444 throw OrthancException(ErrorCode_NotImplemented); |
485 "If present, report the DICOM tags in human-readable format " | 485 "If present, report the DICOM tags in human-readable format " |
486 "(same as the `/instances/{id}/simplified-tags` route)", false) | 486 "(same as the `/instances/{id}/simplified-tags` route)", false) |
487 .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String, | 487 .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String, |
488 "If present, report the DICOM tags indexed in hexadecimal format", false) | 488 "If present, report the DICOM tags indexed in hexadecimal format", false) |
489 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") | 489 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") |
490 .SetHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", true); | 490 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10); |
491 return; | 491 return; |
492 } | 492 } |
493 | 493 |
494 switch (GetDicomFormat(call)) | 494 switch (GetDicomFormat(call)) |
495 { | 495 { |
2375 | 2375 |
2376 template <enum ResourceType start, | 2376 template <enum ResourceType start, |
2377 enum ResourceType end> | 2377 enum ResourceType end> |
2378 static void GetChildResources(RestApiGetCall& call) | 2378 static void GetChildResources(RestApiGetCall& call) |
2379 { | 2379 { |
2380 if (call.IsDocumentation()) | |
2381 { | |
2382 const std::string children = GetResourceTypeText(end, true /* plural */, false /* lower case */); | |
2383 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); | |
2384 call.GetDocumentation() | |
2385 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) | |
2386 .SetSummary("Get child " + children) | |
2387 .SetDescription("Get detailed information about the child " + children + " of the DICOM " + | |
2388 resource + " of interest whose Orthanc identifier is provided in the URL") | |
2389 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") | |
2390 .AddAnswerType(MimeType_Json, "JSON array containing information about the child DICOM " + children) | |
2391 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(start) + "/" + children, 5); | |
2392 return; | |
2393 } | |
2394 | |
2380 ServerIndex& index = OrthancRestApi::GetIndex(call); | 2395 ServerIndex& index = OrthancRestApi::GetIndex(call); |
2381 | 2396 |
2382 std::list<std::string> a, b, c; | 2397 std::list<std::string> a, b, c; |
2383 a.push_back(call.GetUriComponent("id", "")); | 2398 a.push_back(call.GetUriComponent("id", "")); |
2384 | 2399 |
2460 template <enum ResourceType start, | 2475 template <enum ResourceType start, |
2461 enum ResourceType end> | 2476 enum ResourceType end> |
2462 static void GetParentResource(RestApiGetCall& call) | 2477 static void GetParentResource(RestApiGetCall& call) |
2463 { | 2478 { |
2464 assert(start > end); | 2479 assert(start > end); |
2480 | |
2481 if (call.IsDocumentation()) | |
2482 { | |
2483 const std::string parent = GetResourceTypeText(end, false /* plural */, false /* lower case */); | |
2484 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); | |
2485 call.GetDocumentation() | |
2486 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) | |
2487 .SetSummary("Get parent " + parent) | |
2488 .SetDescription("Get detailed information about the parent " + parent + " of the DICOM " + | |
2489 resource + " of interest whose Orthanc identifier is provided in the URL") | |
2490 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") | |
2491 .AddAnswerType(MimeType_Json, "Information about the parent DICOM " + parent) | |
2492 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(start) + "/" + parent, 10); | |
2493 return; | |
2494 } | |
2465 | 2495 |
2466 ServerIndex& index = OrthancRestApi::GetIndex(call); | 2496 ServerIndex& index = OrthancRestApi::GetIndex(call); |
2467 | 2497 |
2468 std::string current = call.GetUriComponent("id", ""); | 2498 std::string current = call.GetUriComponent("id", ""); |
2469 ResourceType currentType = start; | 2499 ResourceType currentType = start; |