comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 4697:569d9ef165b1

Added "short", "simplify" and/or "full" options to control the format of DICOM tags wherever possible
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 18 Jun 2021 16:08:35 +0200
parents da1edb7d6332
children d16c3c7f11ef
comparison
equal deleted inserted replaced
4696:dd6274412ff4 4697:569d9ef165b1
110 call.GetOutput().AnswerJson(dicom); 110 call.GetOutput().AnswerJson(dicom);
111 } 111 }
112 } 112 }
113 113
114 114
115 static DicomToJsonFormat GetDicomFormat(const RestApiGetCall& call)
116 {
117 if (call.HasArgument("simplify"))
118 {
119 return DicomToJsonFormat_Human;
120 }
121 else if (call.HasArgument("short"))
122 {
123 return DicomToJsonFormat_Short;
124 }
125 else
126 {
127 return DicomToJsonFormat_Full;
128 }
129 }
130
131
132 static void AnswerDicomAsJson(RestApiGetCall& call,
133 const Json::Value& dicom)
134 {
135 AnswerDicomAsJson(call, dicom, GetDicomFormat(call));
136 }
137
138
139 static void ParseSetOfTags(std::set<DicomTag>& target, 115 static void ParseSetOfTags(std::set<DicomTag>& target,
140 const RestApiGetCall& call, 116 const RestApiGetCall& call,
141 const std::string& argument) 117 const std::string& argument)
142 { 118 {
143 target.clear(); 119 target.clear();
159 135
160 static void AnswerListOfResources(RestApiOutput& output, 136 static void AnswerListOfResources(RestApiOutput& output,
161 ServerIndex& index, 137 ServerIndex& index,
162 const std::list<std::string>& resources, 138 const std::list<std::string>& resources,
163 ResourceType level, 139 ResourceType level,
164 bool expand) 140 bool expand,
141 DicomToJsonFormat format)
165 { 142 {
166 Json::Value answer = Json::arrayValue; 143 Json::Value answer = Json::arrayValue;
167 144
168 for (std::list<std::string>::const_iterator 145 for (std::list<std::string>::const_iterator
169 resource = resources.begin(); resource != resources.end(); ++resource) 146 resource = resources.begin(); resource != resources.end(); ++resource)
170 { 147 {
171 if (expand) 148 if (expand)
172 { 149 {
173 Json::Value expanded; 150 Json::Value expanded;
174 if (index.ExpandResource(expanded, *resource, level)) 151 if (index.ExpandResource(expanded, *resource, level, format))
175 { 152 {
176 answer.append(expanded); 153 answer.append(expanded);
177 } 154 }
178 } 155 }
179 else 156 else
189 template <enum ResourceType resourceType> 166 template <enum ResourceType resourceType>
190 static void ListResources(RestApiGetCall& call) 167 static void ListResources(RestApiGetCall& call)
191 { 168 {
192 if (call.IsDocumentation()) 169 if (call.IsDocumentation())
193 { 170 {
171 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
172
194 const std::string resources = GetResourceTypeText(resourceType, true /* plural */, false /* lower case */); 173 const std::string resources = GetResourceTypeText(resourceType, true /* plural */, false /* lower case */);
195 call.GetDocumentation() 174 call.GetDocumentation()
196 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) 175 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */))
197 .SetSummary("List the available " + resources) 176 .SetSummary("List the available " + resources)
198 .SetDescription("List the Orthanc identifiers of all the available DICOM " + resources) 177 .SetDescription("List the Orthanc identifiers of all the available DICOM " + resources)
234 else 213 else
235 { 214 {
236 index.GetAllUuids(result, resourceType); 215 index.GetAllUuids(result, resourceType);
237 } 216 }
238 217
239 218 AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand"),
240 AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand")); 219 OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human));
241 } 220 }
242 221
243 222
244 223
245 template <enum ResourceType resourceType> 224 template <enum ResourceType resourceType>
246 static void GetSingleResource(RestApiGetCall& call) 225 static void GetSingleResource(RestApiGetCall& call)
247 { 226 {
248 if (call.IsDocumentation()) 227 if (call.IsDocumentation())
249 { 228 {
229 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
230
250 const std::string resource = GetResourceTypeText(resourceType, false /* plural */, false /* lower case */); 231 const std::string resource = GetResourceTypeText(resourceType, false /* plural */, false /* lower case */);
251 call.GetDocumentation() 232 call.GetDocumentation()
252 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) 233 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */))
253 .SetSummary("Get information about some " + resource) 234 .SetSummary("Get information about some " + resource)
254 .SetDescription("Get detailed information about the DICOM " + resource + " whose Orthanc identifier is provided in the URL") 235 .SetDescription("Get detailed information about the DICOM " + resource + " whose Orthanc identifier is provided in the URL")
256 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) 237 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource)
257 .SetHttpGetSample(GetDocumentationSampleResource(resourceType), true); 238 .SetHttpGetSample(GetDocumentationSampleResource(resourceType), true);
258 return; 239 return;
259 } 240 }
260 241
242 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
243
261 Json::Value json; 244 Json::Value json;
262 if (OrthancRestApi::GetIndex(call).ExpandResource(json, call.GetUriComponent("id", ""), resourceType)) 245 if (OrthancRestApi::GetIndex(call).ExpandResource(
246 json, call.GetUriComponent("id", ""), resourceType, format))
263 { 247 {
264 call.GetOutput().AnswerJson(json); 248 call.GetOutput().AnswerJson(json);
265 } 249 }
266 } 250 }
267 251
419 call.GetOutput().AnswerBuffer("{}", MimeType_Json); 403 call.GetOutput().AnswerBuffer("{}", MimeType_Json);
420 } 404 }
421 405
422 406
423 template <DicomToJsonFormat format> 407 template <DicomToJsonFormat format>
424 static void GetInstanceTags(RestApiGetCall& call) 408 static void GetInstanceTagsInternal(RestApiGetCall& call)
425 { 409 {
426 if (call.IsDocumentation())
427 {
428 if (format == DicomToJsonFormat_Human)
429 {
430 call.GetDocumentation()
431 .SetTag("Instances")
432 .SetSummary("Get human-readable tags")
433 .SetDescription("Get the DICOM tags in human-readable format")
434 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
435 .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings,
436 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false)
437 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
438 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10);
439 return;
440 }
441 else
442 {
443 throw OrthancException(ErrorCode_NotImplemented);
444 }
445 }
446
447 ServerContext& context = OrthancRestApi::GetContext(call); 410 ServerContext& context = OrthancRestApi::GetContext(call);
448 411
449 std::string publicId = call.GetUriComponent("id", ""); 412 std::string publicId = call.GetUriComponent("id", "");
450 413
451 std::set<DicomTag> ignoreTagLength; 414 std::set<DicomTag> ignoreTagLength;
468 call.GetOutput().AnswerJson(full); 431 call.GetOutput().AnswerJson(full);
469 } 432 }
470 } 433 }
471 434
472 435
473 static void GetInstanceTagsBis(RestApiGetCall& call) 436 static void GetInstanceTags(RestApiGetCall& call)
474 { 437 {
475 if (call.IsDocumentation()) 438 if (call.IsDocumentation())
476 { 439 {
440 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
477 call.GetDocumentation() 441 call.GetDocumentation()
478 .SetTag("Instances") 442 .SetTag("Instances")
479 .SetSummary("Get DICOM tags") 443 .SetSummary("Get DICOM tags")
480 .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which " 444 .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which "
481 "combines hexadecimal tags with human-readable description.") 445 "combines hexadecimal tags with human-readable description.")
482 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") 446 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
483 .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String,
484 "If present, report the DICOM tags in human-readable format "
485 "(same as the `/instances/{id}/simplified-tags` route)", false)
486 .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String,
487 "If present, report the DICOM tags indexed in hexadecimal format", false)
488 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") 447 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
489 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10); 448 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10);
490 return; 449 return;
491 } 450 }
492 451
493 switch (GetDicomFormat(call)) 452 switch (OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full))
494 { 453 {
495 case DicomToJsonFormat_Human: 454 case DicomToJsonFormat_Human:
496 GetInstanceTags<DicomToJsonFormat_Human>(call); 455 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call);
497 break; 456 break;
498 457
499 case DicomToJsonFormat_Short: 458 case DicomToJsonFormat_Short:
500 GetInstanceTags<DicomToJsonFormat_Short>(call); 459 GetInstanceTagsInternal<DicomToJsonFormat_Short>(call);
501 break; 460 break;
502 461
503 case DicomToJsonFormat_Full: 462 case DicomToJsonFormat_Full:
504 GetInstanceTags<DicomToJsonFormat_Full>(call); 463 GetInstanceTagsInternal<DicomToJsonFormat_Full>(call);
505 break; 464 break;
506 465
507 default: 466 default:
508 throw OrthancException(ErrorCode_InternalError); 467 throw OrthancException(ErrorCode_InternalError);
509 } 468 }
510 } 469 }
511 470
512 471
472 static void GetInstanceSimplifiedTags(RestApiGetCall& call)
473 {
474 if (call.IsDocumentation())
475 {
476 call.GetDocumentation()
477 .SetTag("Instances")
478 .SetSummary("Get human-readable tags")
479 .SetDescription("Get the DICOM tags in human-readable format (same as the `/instances/{id}/tags?simplify` route)")
480 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
481 .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings,
482 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false)
483 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
484 .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10);
485 return;
486 }
487 else
488 {
489 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call);
490 }
491 }
492
493
513 static void ListFrames(RestApiGetCall& call) 494 static void ListFrames(RestApiGetCall& call)
514 { 495 {
515 if (call.IsDocumentation()) 496 if (call.IsDocumentation())
516 { 497 {
517 call.GetDocumentation() 498 call.GetDocumentation()
2365 2346
2366 static void GetSharedTags(RestApiGetCall& call) 2347 static void GetSharedTags(RestApiGetCall& call)
2367 { 2348 {
2368 if (call.IsDocumentation()) 2349 if (call.IsDocumentation())
2369 { 2350 {
2351 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
2352
2370 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); 2353 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str());
2371 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); 2354 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */);
2372 call.GetDocumentation() 2355 call.GetDocumentation()
2373 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) 2356 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */))
2374 .SetSummary("Get shared tags") 2357 .SetSummary("Get shared tags")
2385 2368
2386 Json::Value sharedTags; 2369 Json::Value sharedTags;
2387 if (ExtractSharedTags(sharedTags, context, publicId)) 2370 if (ExtractSharedTags(sharedTags, context, publicId))
2388 { 2371 {
2389 // Success: Send the value of the shared tags 2372 // Success: Send the value of the shared tags
2390 AnswerDicomAsJson(call, sharedTags); 2373 AnswerDicomAsJson(call, sharedTags, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full));
2391 } 2374 }
2392 } 2375 }
2393
2394
2395 static void GetModuleInternal(RestApiGetCall& call,
2396 ResourceType resourceType,
2397 DicomModule module)
2398 {
2399 if (!((resourceType == ResourceType_Patient && module == DicomModule_Patient) ||
2400 (resourceType == ResourceType_Study && module == DicomModule_Patient) ||
2401 (resourceType == ResourceType_Study && module == DicomModule_Study) ||
2402 (resourceType == ResourceType_Series && module == DicomModule_Series) ||
2403 (resourceType == ResourceType_Instance && module == DicomModule_Instance) ||
2404 (resourceType == ResourceType_Instance && module == DicomModule_Image)))
2405 {
2406 throw OrthancException(ErrorCode_NotImplemented);
2407 }
2408
2409 ServerContext& context = OrthancRestApi::GetContext(call);
2410 std::string publicId = call.GetUriComponent("id", "");
2411
2412 std::set<DicomTag> ignoreTagLength;
2413 ParseSetOfTags(ignoreTagLength, call, "ignore-length");
2414
2415 typedef std::set<DicomTag> ModuleTags;
2416 ModuleTags moduleTags;
2417 DicomTag::AddTagsForModule(moduleTags, module);
2418
2419 Json::Value tags;
2420
2421 if (resourceType != ResourceType_Instance)
2422 {
2423 // Retrieve all the instances of this patient/study/series
2424 typedef std::list<std::string> Instances;
2425 Instances instances;
2426 context.GetIndex().GetChildInstances(instances, publicId);
2427
2428 if (instances.empty())
2429 {
2430 return; // Error: No instance (should never happen)
2431 }
2432
2433 // Select one child instance
2434 publicId = instances.front();
2435 }
2436
2437 context.ReadDicomAsJson(tags, publicId, ignoreTagLength);
2438
2439 // Filter the tags of the instance according to the module
2440 Json::Value result = Json::objectValue;
2441 for (ModuleTags::const_iterator tag = moduleTags.begin(); tag != moduleTags.end(); ++tag)
2442 {
2443 std::string s = tag->Format();
2444 if (tags.isMember(s))
2445 {
2446 result[s] = tags[s];
2447 }
2448 }
2449
2450 AnswerDicomAsJson(call, result);
2451 }
2452
2453 2376
2454 2377
2455 template <enum ResourceType resourceType, 2378 template <enum ResourceType resourceType,
2456 enum DicomModule module> 2379 enum DicomModule module>
2457 static void GetModule(RestApiGetCall& call) 2380 static void GetModule(RestApiGetCall& call)
2475 m = "instance"; 2398 m = "instance";
2476 break; 2399 break;
2477 default: 2400 default:
2478 throw OrthancException(ErrorCode_ParameterOutOfRange); 2401 throw OrthancException(ErrorCode_ParameterOutOfRange);
2479 } 2402 }
2403
2404 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
2405
2480 call.GetDocumentation() 2406 call.GetDocumentation()
2481 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) 2407 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */))
2482 .SetSummary("Get " + m + " module" + std::string(resource == m ? "" : " of " + resource)) 2408 .SetSummary("Get " + m + " module" + std::string(resource == m ? "" : " of " + resource))
2483 .SetDescription("Get the " + m + " module of the DICOM " + resource + " whose Orthanc identifier is provided in the URL") 2409 .SetDescription("Get the " + m + " module of the DICOM " + resource + " whose Orthanc identifier is provided in the URL")
2484 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") 2410 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest")
2487 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) 2413 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource)
2488 .SetHttpGetSample(GetDocumentationSampleResource(resourceType) + "/" + (*call.GetFullUri().rbegin()), true); 2414 .SetHttpGetSample(GetDocumentationSampleResource(resourceType) + "/" + (*call.GetFullUri().rbegin()), true);
2489 return; 2415 return;
2490 } 2416 }
2491 2417
2492 GetModuleInternal(call, resourceType, module); 2418 if (!((resourceType == ResourceType_Patient && module == DicomModule_Patient) ||
2419 (resourceType == ResourceType_Study && module == DicomModule_Patient) ||
2420 (resourceType == ResourceType_Study && module == DicomModule_Study) ||
2421 (resourceType == ResourceType_Series && module == DicomModule_Series) ||
2422 (resourceType == ResourceType_Instance && module == DicomModule_Instance) ||
2423 (resourceType == ResourceType_Instance && module == DicomModule_Image)))
2424 {
2425 throw OrthancException(ErrorCode_NotImplemented);
2426 }
2427
2428 ServerContext& context = OrthancRestApi::GetContext(call);
2429 std::string publicId = call.GetUriComponent("id", "");
2430
2431 std::set<DicomTag> ignoreTagLength;
2432 ParseSetOfTags(ignoreTagLength, call, "ignore-length");
2433
2434 typedef std::set<DicomTag> ModuleTags;
2435 ModuleTags moduleTags;
2436 DicomTag::AddTagsForModule(moduleTags, module);
2437
2438 Json::Value tags;
2439
2440 if (resourceType != ResourceType_Instance)
2441 {
2442 // Retrieve all the instances of this patient/study/series
2443 typedef std::list<std::string> Instances;
2444 Instances instances;
2445 context.GetIndex().GetChildInstances(instances, publicId);
2446
2447 if (instances.empty())
2448 {
2449 return; // Error: No instance (should never happen)
2450 }
2451
2452 // Select one child instance
2453 publicId = instances.front();
2454 }
2455
2456 context.ReadDicomAsJson(tags, publicId, ignoreTagLength);
2457
2458 // Filter the tags of the instance according to the module
2459 Json::Value result = Json::objectValue;
2460 for (ModuleTags::const_iterator tag = moduleTags.begin(); tag != moduleTags.end(); ++tag)
2461 {
2462 std::string s = tag->Format();
2463 if (tags.isMember(s))
2464 {
2465 result[s] = tags[s];
2466 }
2467 }
2468
2469 AnswerDicomAsJson(call, result, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full));
2493 } 2470 }
2494 2471
2495 2472
2496 namespace 2473 namespace
2497 { 2474 {
2565 class FindVisitor : public ServerContext::ILookupVisitor 2542 class FindVisitor : public ServerContext::ILookupVisitor
2566 { 2543 {
2567 private: 2544 private:
2568 bool isComplete_; 2545 bool isComplete_;
2569 std::list<std::string> resources_; 2546 std::list<std::string> resources_;
2547 DicomToJsonFormat format_;
2570 2548
2571 public: 2549 public:
2572 FindVisitor() : 2550 FindVisitor(DicomToJsonFormat format) :
2573 isComplete_(false) 2551 isComplete_(false),
2552 format_(format)
2574 { 2553 {
2575 } 2554 }
2576 2555
2577 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE 2556 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE
2578 { 2557 {
2595 void Answer(RestApiOutput& output, 2574 void Answer(RestApiOutput& output,
2596 ServerIndex& index, 2575 ServerIndex& index,
2597 ResourceType level, 2576 ResourceType level,
2598 bool expand) const 2577 bool expand) const
2599 { 2578 {
2600 AnswerListOfResources(output, index, resources_, level, expand); 2579 AnswerListOfResources(output, index, resources_, level, expand, format_);
2601 } 2580 }
2602 }; 2581 };
2603 } 2582 }
2604 2583
2605 2584
2612 static const char* const KEY_QUERY = "Query"; 2591 static const char* const KEY_QUERY = "Query";
2613 static const char* const KEY_SINCE = "Since"; 2592 static const char* const KEY_SINCE = "Since";
2614 2593
2615 if (call.IsDocumentation()) 2594 if (call.IsDocumentation())
2616 { 2595 {
2596 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
2597
2617 call.GetDocumentation() 2598 call.GetDocumentation()
2618 .SetTag("System") 2599 .SetTag("System")
2619 .SetSummary("Look for local resources") 2600 .SetSummary("Look for local resources")
2620 .SetDescription("This URI can be used to perform a search on the content of the local Orthanc server, " 2601 .SetDescription("This URI can be used to perform a search on the content of the local Orthanc server, "
2621 "in a way that is similar to querying remote DICOM modalities using C-FIND SCU: " 2602 "in a way that is similar to querying remote DICOM modalities using C-FIND SCU: "
2739 query.AddRestConstraint(FromDcmtkBridge::ParseTag(members[i]), 2720 query.AddRestConstraint(FromDcmtkBridge::ParseTag(members[i]),
2740 value, caseSensitive, true); 2721 value, caseSensitive, true);
2741 } 2722 }
2742 } 2723 }
2743 2724
2744 FindVisitor visitor; 2725 FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human));
2745 context.Apply(visitor, query, level, since, limit); 2726 context.Apply(visitor, query, level, since, limit);
2746 visitor.Answer(call.GetOutput(), context.GetIndex(), level, expand); 2727 visitor.Answer(call.GetOutput(), context.GetIndex(), level, expand);
2747 } 2728 }
2748 } 2729 }
2749 2730
2752 enum ResourceType end> 2733 enum ResourceType end>
2753 static void GetChildResources(RestApiGetCall& call) 2734 static void GetChildResources(RestApiGetCall& call)
2754 { 2735 {
2755 if (call.IsDocumentation()) 2736 if (call.IsDocumentation())
2756 { 2737 {
2738 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
2739
2757 const std::string children = GetResourceTypeText(end, true /* plural */, false /* lower case */); 2740 const std::string children = GetResourceTypeText(end, true /* plural */, false /* lower case */);
2758 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); 2741 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */);
2759 call.GetDocumentation() 2742 call.GetDocumentation()
2760 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) 2743 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */))
2761 .SetSummary("Get child " + children) 2744 .SetSummary("Get child " + children)
2790 a.splice(a.begin(), b); 2773 a.splice(a.begin(), b);
2791 } 2774 }
2792 2775
2793 Json::Value result = Json::arrayValue; 2776 Json::Value result = Json::arrayValue;
2794 2777
2778 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
2779
2795 for (std::list<std::string>::const_iterator 2780 for (std::list<std::string>::const_iterator
2796 it = a.begin(); it != a.end(); ++it) 2781 it = a.begin(); it != a.end(); ++it)
2797 { 2782 {
2798 Json::Value resource; 2783 Json::Value resource;
2799 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, *it, end)) 2784 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, *it, end, format))
2800 { 2785 {
2801 result.append(resource); 2786 result.append(resource);
2802 } 2787 }
2803 } 2788 }
2804 2789
2808 2793
2809 static void GetChildInstancesTags(RestApiGetCall& call) 2794 static void GetChildInstancesTags(RestApiGetCall& call)
2810 { 2795 {
2811 if (call.IsDocumentation()) 2796 if (call.IsDocumentation())
2812 { 2797 {
2798 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
2799
2813 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); 2800 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str());
2814 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); 2801 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */);
2815 call.GetDocumentation() 2802 call.GetDocumentation()
2816 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) 2803 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */))
2817 .SetSummary("Get tags of instances") 2804 .SetSummary("Get tags of instances")
2825 return; 2812 return;
2826 } 2813 }
2827 2814
2828 ServerContext& context = OrthancRestApi::GetContext(call); 2815 ServerContext& context = OrthancRestApi::GetContext(call);
2829 std::string publicId = call.GetUriComponent("id", ""); 2816 std::string publicId = call.GetUriComponent("id", "");
2830 DicomToJsonFormat format = GetDicomFormat(call); 2817 DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full);
2831 2818
2832 std::set<DicomTag> ignoreTagLength; 2819 std::set<DicomTag> ignoreTagLength;
2833 ParseSetOfTags(ignoreTagLength, call, "ignore-length"); 2820 ParseSetOfTags(ignoreTagLength, call, "ignore-length");
2834 2821
2835 // Retrieve all the instances of this patient/study/series 2822 // Retrieve all the instances of this patient/study/series
2869 { 2856 {
2870 assert(start > end); 2857 assert(start > end);
2871 2858
2872 if (call.IsDocumentation()) 2859 if (call.IsDocumentation())
2873 { 2860 {
2861 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
2862
2874 const std::string parent = GetResourceTypeText(end, false /* plural */, false /* lower case */); 2863 const std::string parent = GetResourceTypeText(end, false /* plural */, false /* lower case */);
2875 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); 2864 const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */);
2876 call.GetDocumentation() 2865 call.GetDocumentation()
2877 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) 2866 .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */))
2878 .SetSummary("Get parent " + parent) 2867 .SetSummary("Get parent " + parent)
2902 currentType = GetParentResourceType(currentType); 2891 currentType = GetParentResourceType(currentType);
2903 } 2892 }
2904 2893
2905 assert(currentType == end); 2894 assert(currentType == end);
2906 2895
2896 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
2897
2907 Json::Value resource; 2898 Json::Value resource;
2908 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, current, end)) 2899 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, current, end, format))
2909 { 2900 {
2910 call.GetOutput().AnswerJson(resource); 2901 call.GetOutput().AnswerJson(resource);
2911 } 2902 }
2912 } 2903 }
2913 2904
2976 2967
2977 static void GetInstanceHeader(RestApiGetCall& call) 2968 static void GetInstanceHeader(RestApiGetCall& call)
2978 { 2969 {
2979 if (call.IsDocumentation()) 2970 if (call.IsDocumentation())
2980 { 2971 {
2972 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
2981 call.GetDocumentation() 2973 call.GetDocumentation()
2982 .SetTag("Instances") 2974 .SetTag("Instances")
2983 .SetSummary("Get DICOM meta-header") 2975 .SetSummary("Get DICOM meta-header")
2984 .SetDescription("Get the DICOM tags in the meta-header of the DICOM instance. By default, the `full` format is used, which " 2976 .SetDescription("Get the DICOM tags in the meta-header of the DICOM instance. By default, the `full` format is used, which "
2985 "combines hexadecimal tags with human-readable description.") 2977 "combines hexadecimal tags with human-readable description.")
2986 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") 2978 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
2987 .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String,
2988 "If present, report the DICOM tags in human-readable format", false)
2989 .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String,
2990 "If present, report the DICOM tags indexed in hexadecimal format", false)
2991 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") 2979 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
2992 .SetHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/header", true); 2980 .SetHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/header", true);
2993 return; 2981 return;
2994 } 2982 }
2995 2983
3006 ParsedDicomFile dicom(dicomContent); 2994 ParsedDicomFile dicom(dicomContent);
3007 2995
3008 Json::Value header; 2996 Json::Value header;
3009 OrthancConfiguration::DefaultDicomHeaderToJson(header, dicom); 2997 OrthancConfiguration::DefaultDicomHeaderToJson(header, dicom);
3010 2998
3011 AnswerDicomAsJson(call, header); 2999 AnswerDicomAsJson(call, header, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full));
3012 } 3000 }
3013 3001
3014 3002
3015 static void InvalidateTags(RestApiPostCall& call) 3003 static void InvalidateTags(RestApiPostCall& call)
3016 { 3004 {
3181 Register("/studies/{id}/module", GetModule<ResourceType_Study, DicomModule_Study>); 3169 Register("/studies/{id}/module", GetModule<ResourceType_Study, DicomModule_Study>);
3182 Register("/studies/{id}/module-patient", GetModule<ResourceType_Study, DicomModule_Patient>); 3170 Register("/studies/{id}/module-patient", GetModule<ResourceType_Study, DicomModule_Patient>);
3183 3171
3184 Register("/instances/{id}/file", GetInstanceFile); 3172 Register("/instances/{id}/file", GetInstanceFile);
3185 Register("/instances/{id}/export", ExportInstanceFile); 3173 Register("/instances/{id}/export", ExportInstanceFile);
3186 Register("/instances/{id}/tags", GetInstanceTagsBis); 3174 Register("/instances/{id}/tags", GetInstanceTags);
3187 Register("/instances/{id}/simplified-tags", GetInstanceTags<DicomToJsonFormat_Human>); 3175 Register("/instances/{id}/simplified-tags", GetInstanceSimplifiedTags);
3188 Register("/instances/{id}/frames", ListFrames); 3176 Register("/instances/{id}/frames", ListFrames);
3189 3177
3190 Register("/instances/{id}/frames/{frame}", RestApi::AutoListChildren); 3178 Register("/instances/{id}/frames/{frame}", RestApi::AutoListChildren);
3191 Register("/instances/{id}/frames/{frame}/preview", GetImage<ImageExtractionMode_Preview>); 3179 Register("/instances/{id}/frames/{frame}/preview", GetImage<ImageExtractionMode_Preview>);
3192 Register("/instances/{id}/frames/{frame}/rendered", GetRenderedFrame); 3180 Register("/instances/{id}/frames/{frame}/rendered", GetRenderedFrame);