comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 4935:acd3f72e2a21 more-tags

split ExpandResource in 2: read from DB and serialize to json. This will allow us to merge requested tags from both the DB and the file system
author Alain Mazy <am@osimis.io>
date Thu, 10 Mar 2022 19:00:43 +0100
parents df86d2505df8
children 8422e4f99a18
comparison
equal deleted inserted replaced
4934:94a7b681b340 4935:acd3f72e2a21
124 124
125 125
126 // List all the patients, studies, series or instances ---------------------- 126 // List all the patients, studies, series or instances ----------------------
127 127
128 static void AnswerListOfResources(RestApiOutput& output, 128 static void AnswerListOfResources(RestApiOutput& output,
129 ServerIndex& index, 129 ServerContext& context,
130 const std::list<std::string>& resources, 130 const std::list<std::string>& resources,
131 ResourceType level, 131 ResourceType level,
132 bool expand, 132 bool expand,
133 DicomToJsonFormat format) 133 DicomToJsonFormat format)
134 { 134 {
138 resource = resources.begin(); resource != resources.end(); ++resource) 138 resource = resources.begin(); resource != resources.end(); ++resource)
139 { 139 {
140 if (expand) 140 if (expand)
141 { 141 {
142 Json::Value expanded; 142 Json::Value expanded;
143 if (index.ExpandResource(expanded, *resource, level, format)) 143 if (context.ExpandResource(expanded, *resource, level, format))
144 { 144 {
145 answer.append(expanded); 145 answer.append(expanded);
146 } 146 }
147 } 147 }
148 else 148 else
176 .SetHttpGetSample("https://demo.orthanc-server.com/" + resources + "?since=0&limit=2", true); 176 .SetHttpGetSample("https://demo.orthanc-server.com/" + resources + "?since=0&limit=2", true);
177 return; 177 return;
178 } 178 }
179 179
180 ServerIndex& index = OrthancRestApi::GetIndex(call); 180 ServerIndex& index = OrthancRestApi::GetIndex(call);
181 ServerContext& context = OrthancRestApi::GetContext(call);
181 182
182 std::list<std::string> result; 183 std::list<std::string> result;
183 184
184 if (call.HasArgument("limit") || 185 if (call.HasArgument("limit") ||
185 call.HasArgument("since")) 186 call.HasArgument("since"))
205 else 206 else
206 { 207 {
207 index.GetAllUuids(result, resourceType); 208 index.GetAllUuids(result, resourceType);
208 } 209 }
209 210
210 AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand"), 211 AnswerListOfResources(call.GetOutput(), context, result, resourceType, call.HasArgument("expand"),
211 OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); 212 OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human));
212 } 213 }
213 214
214 215
215 216
224 call.GetDocumentation() 225 call.GetDocumentation()
225 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) 226 .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */))
226 .SetSummary("Get information about some " + resource) 227 .SetSummary("Get information about some " + resource)
227 .SetDescription("Get detailed information about the DICOM " + resource + " whose Orthanc identifier is provided in the URL") 228 .SetDescription("Get detailed information about the DICOM " + resource + " whose Orthanc identifier is provided in the URL")
228 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") 229 .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest")
230 .SetHttpGetArgument("requestedTags", RestApiCallDocumentation::Type_String,
231 "If present, list the DICOM Tags you want to list in the response. This argument is a semi-column separated list "
232 "of DICOM Tags identifiers; e.g: 'requestedTags=0010,0010;PatientBirthDate'. "
233 "The tags requested tags are returned in the 'RequestedTags' field in the response. "
234 "Note that, if you are requesting tags that are not listed in the Main Dicom Tags stored in DB, building the response "
235 "might be slow since Orthanc will need to access the DICOM files. If not specified, Orthanc will return ", false)
229 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) 236 .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource)
230 .SetHttpGetSample(GetDocumentationSampleResource(resourceType), true); 237 .SetHttpGetSample(GetDocumentationSampleResource(resourceType), true);
231 return; 238 return;
232 } 239 }
233 240
234 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); 241 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
235 242
243 std::set<DicomTag> responseTags;
244 if (call.HasArgument("requestedTags"))
245 {
246 try
247 {
248 FromDcmtkBridge::ParseListOfTags(responseTags, call.GetArgument("requestedTags", ""));
249 }
250 catch (OrthancException& ex)
251 {
252 throw OrthancException(ErrorCode_BadRequest, std::string("Invalid requestedTags argument: ") + ex.What() + " " + ex.GetDetails());
253 }
254 }
255
236 Json::Value json; 256 Json::Value json;
237 if (OrthancRestApi::GetIndex(call).ExpandResource( 257 if (OrthancRestApi::GetContext(call).ExpandResource(
238 json, call.GetUriComponent("id", ""), resourceType, format)) 258 json, call.GetUriComponent("id", ""), resourceType, format)) // TODO, requestedTags))
239 { 259 {
240 call.GetOutput().AnswerJson(json); 260 call.GetOutput().AnswerJson(json);
241 } 261 }
242 } 262 }
243 263
2843 { 2863 {
2844 resources_.push_back(publicId); 2864 resources_.push_back(publicId);
2845 } 2865 }
2846 2866
2847 void Answer(RestApiOutput& output, 2867 void Answer(RestApiOutput& output,
2848 ServerIndex& index, 2868 ServerContext& context,
2849 ResourceType level, 2869 ResourceType level,
2850 bool expand) const 2870 bool expand) const
2851 { 2871 {
2852 AnswerListOfResources(output, index, resources_, level, expand, format_); 2872 AnswerListOfResources(output, context, resources_, level, expand, format_);
2853 } 2873 }
2854 }; 2874 };
2855 } 2875 }
2856 2876
2857 2877
2860 static const char* const KEY_CASE_SENSITIVE = "CaseSensitive"; 2880 static const char* const KEY_CASE_SENSITIVE = "CaseSensitive";
2861 static const char* const KEY_EXPAND = "Expand"; 2881 static const char* const KEY_EXPAND = "Expand";
2862 static const char* const KEY_LEVEL = "Level"; 2882 static const char* const KEY_LEVEL = "Level";
2863 static const char* const KEY_LIMIT = "Limit"; 2883 static const char* const KEY_LIMIT = "Limit";
2864 static const char* const KEY_QUERY = "Query"; 2884 static const char* const KEY_QUERY = "Query";
2885 static const char* const KEY_REQUESTED_TAGS = "RequestedTags";
2865 static const char* const KEY_SINCE = "Since"; 2886 static const char* const KEY_SINCE = "Since";
2866 2887
2867 if (call.IsDocumentation()) 2888 if (call.IsDocumentation())
2868 { 2889 {
2869 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); 2890 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
2882 "Level of the query (`Patient`, `Study`, `Series` or `Instance`)", true) 2903 "Level of the query (`Patient`, `Study`, `Series` or `Instance`)", true)
2883 .SetRequestField(KEY_LIMIT, RestApiCallDocumentation::Type_Number, 2904 .SetRequestField(KEY_LIMIT, RestApiCallDocumentation::Type_Number,
2884 "Limit the number of reported resources", false) 2905 "Limit the number of reported resources", false)
2885 .SetRequestField(KEY_SINCE, RestApiCallDocumentation::Type_Number, 2906 .SetRequestField(KEY_SINCE, RestApiCallDocumentation::Type_Number,
2886 "Show only the resources since the provided index (in conjunction with `Limit`)", false) 2907 "Show only the resources since the provided index (in conjunction with `Limit`)", false)
2908 .SetRequestField(KEY_REQUESTED_TAGS, RestApiCallDocumentation::Type_JsonListOfStrings,
2909 "A list of DICOM tags to include in the response (applicable only if \"Expand\" is set to true). "
2910 "The tags requested tags are returned in the 'RequestedTags' field in the response. "
2911 "Note that, if you are requesting tags that are not listed in the Main Dicom Tags stored in DB, building the response "
2912 "might be slow since Orthanc will need to access the DICOM files. If not specified, Orthanc will return "
2913 "all Main Dicom Tags to keep backward compatibility with Orthanc prior to 1.11.0.", false)
2914
2887 .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject, 2915 .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject,
2888 "Associative array containing the filter on the values of the DICOM tags", true) 2916 "Associative array containing the filter on the values of the DICOM tags", true)
2889 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information " 2917 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information "
2890 "about the reported resources (if `Expand` argument is `true`)"); 2918 "about the reported resources (if `Expand` argument is `true`)");
2891 return; 2919 return;
2892 } 2920 }
2893 2921
2894 ServerContext& context = OrthancRestApi::GetContext(call); 2922 ServerContext& context = OrthancRestApi::GetContext(call);
2923
2924 // MORE_TAGS: TODO: handle RequestedTags
2895 2925
2896 Json::Value request; 2926 Json::Value request;
2897 if (!call.ParseJsonRequest(request) || 2927 if (!call.ParseJsonRequest(request) ||
2898 request.type() != Json::objectValue) 2928 request.type() != Json::objectValue)
2899 { 2929 {
2995 } 3025 }
2996 } 3026 }
2997 3027
2998 FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human)); 3028 FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human));
2999 context.Apply(visitor, query, level, since, limit); 3029 context.Apply(visitor, query, level, since, limit);
3000 visitor.Answer(call.GetOutput(), context.GetIndex(), level, expand); 3030 visitor.Answer(call.GetOutput(), context, level, expand);
3001 } 3031 }
3002 } 3032 }
3003 3033
3004 3034
3005 template <enum ResourceType start, 3035 template <enum ResourceType start,
3052 3082
3053 for (std::list<std::string>::const_iterator 3083 for (std::list<std::string>::const_iterator
3054 it = a.begin(); it != a.end(); ++it) 3084 it = a.begin(); it != a.end(); ++it)
3055 { 3085 {
3056 Json::Value resource; 3086 Json::Value resource;
3057 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, *it, end, format)) 3087 if (OrthancRestApi::GetContext(call).ExpandResource(resource, *it, end, format))
3058 { 3088 {
3059 result.append(resource); 3089 result.append(resource);
3060 } 3090 }
3061 } 3091 }
3062 3092
3167 assert(currentType == end); 3197 assert(currentType == end);
3168 3198
3169 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); 3199 const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
3170 3200
3171 Json::Value resource; 3201 Json::Value resource;
3172 if (OrthancRestApi::GetIndex(call).ExpandResource(resource, current, end, format)) 3202 if (OrthancRestApi::GetContext(call).ExpandResource(resource, current, end, format))
3173 { 3203 {
3174 call.GetOutput().AnswerJson(resource); 3204 call.GetOutput().AnswerJson(resource);
3175 } 3205 }
3176 } 3206 }
3177 3207
3539 3569
3540 for (std::set<std::string>::const_iterator 3570 for (std::set<std::string>::const_iterator
3541 it = interest.begin(); it != interest.end(); ++it) 3571 it = interest.begin(); it != interest.end(); ++it)
3542 { 3572 {
3543 Json::Value item; 3573 Json::Value item;
3544 if (index.ExpandResource(item, *it, level, format)) 3574 if (OrthancRestApi::GetContext(call).ExpandResource(item, *it, level, format))
3545 { 3575 {
3546 if (metadata) 3576 if (metadata)
3547 { 3577 {
3548 AddMetadata(item[METADATA], index, *it, level); 3578 AddMetadata(item[METADATA], index, *it, level);
3549 } 3579 }
3562 it = resources.begin(); it != resources.end(); ++it) 3592 it = resources.begin(); it != resources.end(); ++it)
3563 { 3593 {
3564 ResourceType level; 3594 ResourceType level;
3565 Json::Value item; 3595 Json::Value item;
3566 if (index.LookupResourceType(level, *it) && 3596 if (index.LookupResourceType(level, *it) &&
3567 index.ExpandResource(item, *it, level, format)) 3597 OrthancRestApi::GetContext(call).ExpandResource(item, *it, level, format))
3568 { 3598 {
3569 if (metadata) 3599 if (metadata)
3570 { 3600 {
3571 AddMetadata(item[METADATA], index, *it, level); 3601 AddMetadata(item[METADATA], index, *it, level);
3572 } 3602 }