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;