comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 5227:988dab8deb1c db-protobuf

"/tools/find" accepts the "WithLabels" and "WithoutLabels" arguments
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Apr 2023 09:16:12 +0200
parents d0f7c742d397
children a7d95f951f8a
comparison
equal deleted inserted replaced
5226:49e906a8fea2 5227:988dab8deb1c
3070 static const char* const KEY_LEVEL = "Level"; 3070 static const char* const KEY_LEVEL = "Level";
3071 static const char* const KEY_LIMIT = "Limit"; 3071 static const char* const KEY_LIMIT = "Limit";
3072 static const char* const KEY_QUERY = "Query"; 3072 static const char* const KEY_QUERY = "Query";
3073 static const char* const KEY_REQUESTED_TAGS = "RequestedTags"; 3073 static const char* const KEY_REQUESTED_TAGS = "RequestedTags";
3074 static const char* const KEY_SINCE = "Since"; 3074 static const char* const KEY_SINCE = "Since";
3075 static const char* const KEY_WITH_LABELS = "WithLabels"; // New in Orthanc 1.12.0
3076 static const char* const KEY_WITHOUT_LABELS = "WithoutLabels"; // New in Orthanc 1.12.0
3075 3077
3076 if (call.IsDocumentation()) 3078 if (call.IsDocumentation())
3077 { 3079 {
3078 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); 3080 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human);
3079 3081
3099 "Note that, if you are requesting tags that are not listed in the Main Dicom Tags stored in DB, building the response " 3101 "Note that, if you are requesting tags that are not listed in the Main Dicom Tags stored in DB, building the response "
3100 "might be slow since Orthanc will need to access the DICOM files. If not specified, Orthanc will return " 3102 "might be slow since Orthanc will need to access the DICOM files. If not specified, Orthanc will return "
3101 "all Main Dicom Tags to keep backward compatibility with Orthanc prior to 1.11.0.", false) 3103 "all Main Dicom Tags to keep backward compatibility with Orthanc prior to 1.11.0.", false)
3102 .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject, 3104 .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject,
3103 "Associative array containing the filter on the values of the DICOM tags", true) 3105 "Associative array containing the filter on the values of the DICOM tags", true)
3106 .SetRequestField(KEY_WITH_LABELS, RestApiCallDocumentation::Type_JsonListOfStrings,
3107 "List of strings specifying which labels must be present in the resources (new in Orthanc 1.12.0)", true)
3108 .SetRequestField(KEY_WITHOUT_LABELS, RestApiCallDocumentation::Type_JsonListOfStrings,
3109 "List of strings specifying which labels must not be present in the resources (new in Orthanc 1.12.0)", true)
3104 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information " 3110 .AddAnswerType(MimeType_Json, "JSON array containing either the Orthanc identifiers, or detailed information "
3105 "about the reported resources (if `Expand` argument is `true`)"); 3111 "about the reported resources (if `Expand` argument is `true`)");
3106 return; 3112 return;
3107 } 3113 }
3108 3114
3129 } 3135 }
3130 else if (request.isMember(KEY_CASE_SENSITIVE) && 3136 else if (request.isMember(KEY_CASE_SENSITIVE) &&
3131 request[KEY_CASE_SENSITIVE].type() != Json::booleanValue) 3137 request[KEY_CASE_SENSITIVE].type() != Json::booleanValue)
3132 { 3138 {
3133 throw OrthancException(ErrorCode_BadRequest, 3139 throw OrthancException(ErrorCode_BadRequest,
3134 "Field \"" + std::string(KEY_CASE_SENSITIVE) + "\" should be a Boolean"); 3140 "Field \"" + std::string(KEY_CASE_SENSITIVE) + "\" must be a Boolean");
3135 } 3141 }
3136 else if (request.isMember(KEY_LIMIT) && 3142 else if (request.isMember(KEY_LIMIT) &&
3137 request[KEY_LIMIT].type() != Json::intValue) 3143 request[KEY_LIMIT].type() != Json::intValue)
3138 { 3144 {
3139 throw OrthancException(ErrorCode_BadRequest, 3145 throw OrthancException(ErrorCode_BadRequest,
3140 "Field \"" + std::string(KEY_LIMIT) + "\" should be an integer"); 3146 "Field \"" + std::string(KEY_LIMIT) + "\" must be an integer");
3141 } 3147 }
3142 else if (request.isMember(KEY_SINCE) && 3148 else if (request.isMember(KEY_SINCE) &&
3143 request[KEY_SINCE].type() != Json::intValue) 3149 request[KEY_SINCE].type() != Json::intValue)
3144 { 3150 {
3145 throw OrthancException(ErrorCode_BadRequest, 3151 throw OrthancException(ErrorCode_BadRequest,
3146 "Field \"" + std::string(KEY_SINCE) + "\" should be an integer"); 3152 "Field \"" + std::string(KEY_SINCE) + "\" must be an integer");
3147 } 3153 }
3148 else if (request.isMember(KEY_REQUESTED_TAGS) && 3154 else if (request.isMember(KEY_REQUESTED_TAGS) &&
3149 request[KEY_REQUESTED_TAGS].type() != Json::arrayValue) 3155 request[KEY_REQUESTED_TAGS].type() != Json::arrayValue)
3150 { 3156 {
3151 throw OrthancException(ErrorCode_BadRequest, 3157 throw OrthancException(ErrorCode_BadRequest,
3152 "Field \"" + std::string(KEY_REQUESTED_TAGS) + "\" should be an array"); 3158 "Field \"" + std::string(KEY_REQUESTED_TAGS) + "\" must be an array");
3159 }
3160 else if (request.isMember(KEY_WITH_LABELS) &&
3161 request[KEY_WITH_LABELS].type() != Json::arrayValue)
3162 {
3163 throw OrthancException(ErrorCode_BadRequest,
3164 "Field \"" + std::string(KEY_WITH_LABELS) + "\" must be an array of strings");
3165 }
3166 else if (request.isMember(KEY_WITHOUT_LABELS) &&
3167 request[KEY_WITHOUT_LABELS].type() != Json::arrayValue)
3168 {
3169 throw OrthancException(ErrorCode_BadRequest,
3170 "Field \"" + std::string(KEY_WITHOUT_LABELS) + "\" must be an array of strings");
3153 } 3171 }
3154 else 3172 else
3155 { 3173 {
3156 bool expand = false; 3174 bool expand = false;
3157 if (request.isMember(KEY_EXPAND)) 3175 if (request.isMember(KEY_EXPAND))
3170 { 3188 {
3171 int tmp = request[KEY_LIMIT].asInt(); 3189 int tmp = request[KEY_LIMIT].asInt();
3172 if (tmp < 0) 3190 if (tmp < 0)
3173 { 3191 {
3174 throw OrthancException(ErrorCode_ParameterOutOfRange, 3192 throw OrthancException(ErrorCode_ParameterOutOfRange,
3175 "Field \"" + std::string(KEY_LIMIT) + "\" should be a positive integer"); 3193 "Field \"" + std::string(KEY_LIMIT) + "\" must be a positive integer");
3176 } 3194 }
3177 3195
3178 limit = static_cast<size_t>(tmp); 3196 limit = static_cast<size_t>(tmp);
3179 } 3197 }
3180 3198
3183 { 3201 {
3184 int tmp = request[KEY_SINCE].asInt(); 3202 int tmp = request[KEY_SINCE].asInt();
3185 if (tmp < 0) 3203 if (tmp < 0)
3186 { 3204 {
3187 throw OrthancException(ErrorCode_ParameterOutOfRange, 3205 throw OrthancException(ErrorCode_ParameterOutOfRange,
3188 "Field \"" + std::string(KEY_SINCE) + "\" should be a positive integer"); 3206 "Field \"" + std::string(KEY_SINCE) + "\" must be a positive integer");
3189 } 3207 }
3190 3208
3191 since = static_cast<size_t>(tmp); 3209 since = static_cast<size_t>(tmp);
3192 } 3210 }
3193 3211
3206 for (size_t i = 0; i < members.size(); i++) 3224 for (size_t i = 0; i < members.size(); i++)
3207 { 3225 {
3208 if (request[KEY_QUERY][members[i]].type() != Json::stringValue) 3226 if (request[KEY_QUERY][members[i]].type() != Json::stringValue)
3209 { 3227 {
3210 throw OrthancException(ErrorCode_BadRequest, 3228 throw OrthancException(ErrorCode_BadRequest,
3211 "Tag \"" + members[i] + "\" should be associated with a string"); 3229 "Tag \"" + members[i] + "\" must be associated with a string");
3212 } 3230 }
3213 3231
3214 const std::string value = request[KEY_QUERY][members[i]].asString(); 3232 const std::string value = request[KEY_QUERY][members[i]].asString();
3215 3233
3216 if (!value.empty()) 3234 if (!value.empty())
3221 query.AddRestConstraint(FromDcmtkBridge::ParseTag(members[i]), 3239 query.AddRestConstraint(FromDcmtkBridge::ParseTag(members[i]),
3222 value, caseSensitive, true); 3240 value, caseSensitive, true);
3223 } 3241 }
3224 } 3242 }
3225 3243
3244 if (request.isMember(KEY_WITH_LABELS)) // New in Orthanc 1.12.0
3245 {
3246 for (Json::Value::ArrayIndex i = 0; i < request[KEY_WITH_LABELS].size(); i++)
3247 {
3248 if (request[KEY_WITH_LABELS][i].type() != Json::stringValue)
3249 {
3250 throw OrthancException(ErrorCode_BadRequest, "Field \""+ std::string(KEY_WITH_LABELS) + "\" must contain strings");
3251 }
3252 else
3253 {
3254 query.AddWithLabel(request[KEY_WITH_LABELS][i].asString());
3255 }
3256 }
3257 }
3258
3259 if (request.isMember(KEY_WITHOUT_LABELS)) // New in Orthanc 1.12.0
3260 {
3261 for (Json::Value::ArrayIndex i = 0; i < request[KEY_WITHOUT_LABELS].size(); i++)
3262 {
3263 if (request[KEY_WITHOUT_LABELS][i].type() != Json::stringValue)
3264 {
3265 throw OrthancException(ErrorCode_BadRequest, "Field \""+ std::string(KEY_WITHOUT_LABELS) + "\" must contain strings");
3266 }
3267 else
3268 {
3269 query.AddWithoutLabel(request[KEY_WITHOUT_LABELS][i].asString());
3270 }
3271 }
3272 }
3273
3226 FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human), context.GetFindStorageAccessMode()); 3274 FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human), context.GetFindStorageAccessMode());
3227 context.Apply(visitor, query, level, since, limit); 3275 context.Apply(visitor, query, level, since, limit);
3228 visitor.Answer(call.GetOutput(), context, level, expand, requestedTags); 3276 visitor.Answer(call.GetOutput(), context, level, expand, requestedTags);
3229 } 3277 }
3230 } 3278 }