# HG changeset patch # User Sebastien Jodogne # Date 1720799669 -7200 # Node ID 1404a80dd46130f21cf094d8e48cd70e165071da # Parent 0c2f0d72d143ffd833c32cfab8c9fed64863d073# Parent eb56ee3c5d633bd1583ff1c589dc414f05d25f06 integration find-refactoring->find-refactoring-clean diff -r eb56ee3c5d63 -r 1404a80dd461 OrthancServer/Sources/OrthancFindRequestHandler.cpp --- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp Fri Jul 12 17:51:52 2024 +0200 +++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp Fri Jul 12 17:54:29 2024 +0200 @@ -82,102 +82,6 @@ } - static void AddAnswer(DicomFindAnswers& answers, - ServerContext& context, - const std::string& publicId, - const std::string& instanceId, - const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson, - ResourceType level, - const DicomArray& query, - const std::list& sequencesToReturn, - const std::string& defaultPrivateCreator, - const std::map& privateCreators, - const std::string& retrieveAet, - bool allowStorageAccess) - { - ExpandedResource resource; - std::set requestedTags; - - query.GetTags(requestedTags); - requestedTags.erase(DICOM_TAG_QUERY_RETRIEVE_LEVEL); // this is not part of the answer - - // reuse ExpandResource to get missing tags and computed tags (ModalitiesInStudy ...). This code is therefore shared between C-Find, tools/find, list-resources and QIDO-RS - context.ExpandResource(resource, publicId, mainDicomTags, instanceId, dicomAsJson, - level, requestedTags, ExpandResourceFlags_IncludeMainDicomTags, allowStorageAccess); - - DicomMap result; - - /** - * Add the mandatory "Retrieve AE Title (0008,0054)" tag, which was missing in Orthanc <= 1.7.2. - * http://dicom.nema.org/medical/dicom/current/output/html/part04.html#sect_C.4.1.1.3.2 - * https://groups.google.com/g/orthanc-users/c/-7zNTKR_PMU/m/kfjwzEVNAgAJ - **/ - result.SetValue(DICOM_TAG_RETRIEVE_AE_TITLE, retrieveAet, false /* not binary */); - - for (size_t i = 0; i < query.GetSize(); i++) - { - if (query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL) - { - // Fix issue 30 on Google Code (QR response missing "Query/Retrieve Level" (008,0052)) - result.SetValue(query.GetElement(i).GetTag(), query.GetElement(i).GetValue()); - } - else if (query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET) - { - // Do not include the encoding, this is handled by class ParsedDicomFile - } - else - { - const DicomTag& tag = query.GetElement(i).GetTag(); - const DicomValue* value = resource.GetMainDicomTags().TestAndGetValue(tag); - - if (value != NULL && - !value->IsNull() && - !value->IsBinary()) - { - result.SetValue(tag, value->GetContent(), false); - } - else - { - result.SetValue(tag, "", false); - } - } - } - - if (result.GetSize() == 0 && - sequencesToReturn.empty()) - { - CLOG(WARNING, DICOM) << "The C-FIND request does not return any DICOM tag"; - } - else if (sequencesToReturn.empty()) - { - answers.Add(result); - } - else if (dicomAsJson == NULL) - { - CLOG(WARNING, DICOM) << "C-FIND query requesting a sequence, but reading JSON from disk is disabled"; - answers.Add(result); - } - else - { - ParsedDicomFile dicom(result, GetDefaultDicomEncoding(), - true /* be permissive, cf. issue #136 */, defaultPrivateCreator, privateCreators); - - for (std::list::const_iterator tag = sequencesToReturn.begin(); - tag != sequencesToReturn.end(); ++tag) - { - assert(dicomAsJson != NULL); - const Json::Value& source = (*dicomAsJson) [tag->Format()]; - - CopySequence(dicom, *tag, source, defaultPrivateCreator, privateCreators); - } - - answers.Add(dicom); - } - } - - - bool OrthancFindRequestHandler::FilterQueryTag(std::string& value /* can be modified */, ResourceType level, const DicomTag& tag, @@ -248,88 +152,6 @@ } - class OrthancFindRequestHandler::LookupVisitor : public ServerContext::ILookupVisitor - { - private: - DicomFindAnswers& answers_; - ServerContext& context_; - ResourceType level_; - const DicomMap& query_; - DicomArray queryAsArray_; - const std::list& sequencesToReturn_; - std::string defaultPrivateCreator_; // the private creator to use if the group is not defined in the query itself - const std::map& privateCreators_; // the private creators defined in the query itself - std::string retrieveAet_; - FindStorageAccessMode findStorageAccessMode_; - - public: - LookupVisitor(DicomFindAnswers& answers, - ServerContext& context, - ResourceType level, - const DicomMap& query, - const std::list& sequencesToReturn, - const std::map& privateCreators, - FindStorageAccessMode findStorageAccessMode) : - answers_(answers), - context_(context), - level_(level), - query_(query), - queryAsArray_(query), - sequencesToReturn_(sequencesToReturn), - privateCreators_(privateCreators), - findStorageAccessMode_(findStorageAccessMode) - { - answers_.SetComplete(false); - - { - OrthancConfiguration::ReaderLock lock; - defaultPrivateCreator_ = lock.GetConfiguration().GetDefaultPrivateCreator(); - retrieveAet_ = lock.GetConfiguration().GetOrthancAET(); - } - } - - virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE - { - // Ask the "DICOM-as-JSON" attachment only if sequences are to - // be returned OR if "query_" contains non-main DICOM tags! - - DicomMap withoutSpecialTags; - withoutSpecialTags.Assign(query_); - - // Check out "ComputeCounters()" - withoutSpecialTags.Remove(DICOM_TAG_MODALITIES_IN_STUDY); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES); - withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES); - withoutSpecialTags.Remove(DICOM_TAG_SOP_CLASSES_IN_STUDY); - - // Check out "AddAnswer()" - withoutSpecialTags.Remove(DICOM_TAG_SPECIFIC_CHARACTER_SET); - withoutSpecialTags.Remove(DICOM_TAG_QUERY_RETRIEVE_LEVEL); - - return (!sequencesToReturn_.empty() || - !withoutSpecialTags.HasOnlyMainDicomTags()); - } - - virtual void MarkAsComplete() ORTHANC_OVERRIDE - { - answers_.SetComplete(true); - } - - virtual void Visit(const std::string& publicId, - const std::string& instanceId, - const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson) ORTHANC_OVERRIDE - { - AddAnswer(answers_, context_, publicId, instanceId, mainDicomTags, dicomAsJson, level_, queryAsArray_, sequencesToReturn_, - defaultPrivateCreator_, privateCreators_, retrieveAet_, IsStorageAccessAllowedForAnswers(findStorageAccessMode_)); - } - }; - - namespace { class LookupVisitorV2 : public ResourceFinder::IVisitor @@ -622,31 +444,12 @@ * Run the query. **/ - size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; - - - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - - ResourceFinder finder(level, false /* don't expand */); - finder.SetDatabaseLookup(lookup); - finder.AddRequestedTags(requestedTags); + ResourceFinder finder(level, false /* don't expand */); + finder.SetDatabaseLookup(lookup); + finder.AddRequestedTags(requestedTags); - LookupVisitorV2 visitor(answers, *filteredInput, sequencesToReturn, privateCreators); - finder.Execute(visitor, context_); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - - LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn, privateCreators, context_.GetFindStorageAccessMode()); - context_.Apply(visitor, lookup, level, 0 /* "since" is not relevant to C-FIND */, limit); - } + LookupVisitorV2 visitor(answers, *filteredInput, sequencesToReturn, privateCreators); + finder.Execute(visitor, context_); } diff -r eb56ee3c5d63 -r 1404a80dd461 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Jul 12 17:51:52 2024 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Jul 12 17:54:29 2024 +0200 @@ -131,77 +131,6 @@ // List all the patients, studies, series or instances ---------------------- - static void AnswerListOfResources1(RestApiOutput& output, - ServerContext& context, - const std::list& resources, - const std::map& instancesIds, // optional: the id of an instance for each found resource. - const std::map >& resourcesMainDicomTags, // optional: all tags read from DB for a resource (current level and upper levels) - const std::map >& resourcesDicomAsJson, // optional: the dicom-as-json for each resource - ResourceType level, - bool expand, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess) - { - Json::Value answer = Json::arrayValue; - - for (std::list::const_iterator - resource = resources.begin(); resource != resources.end(); ++resource) - { - if (expand) - { - Json::Value expanded; - - std::map::const_iterator instanceId = instancesIds.find(*resource); - if (instanceId != instancesIds.end()) // if it is found in instancesIds, it is also in resourcesDicomAsJson and mainDicomTags - { - // reuse data already collected before (e.g during lookup) - std::map >::const_iterator mainDicomTags = resourcesMainDicomTags.find(*resource); - std::map >::const_iterator dicomAsJson = resourcesDicomAsJson.find(*resource); - - context.ExpandResource(expanded, *resource, - *(mainDicomTags->second.get()), - instanceId->second, - dicomAsJson->second.get(), - level, format, requestedTags, allowStorageAccess); - } - else - { - context.ExpandResource(expanded, *resource, level, format, requestedTags, allowStorageAccess); - } - - if (expanded.type() == Json::objectValue) - { - answer.append(expanded); - } - } - else - { - answer.append(*resource); - } - } - - output.AnswerJson(answer); - } - - - static void AnswerListOfResources2(RestApiOutput& output, - ServerContext& context, - const std::list& resources, - ResourceType level, - bool expand, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess) - { - std::map unusedInstancesIds; - std::map > unusedResourcesMainDicomTags; - std::map > unusedResourcesDicomAsJson; - - AnswerListOfResources1(output, context, resources, unusedInstancesIds, unusedResourcesMainDicomTags, unusedResourcesDicomAsJson, level, expand, format, requestedTags, allowStorageAccess); - } - - template static void ListResources(RestApiGetCall& call) { @@ -224,97 +153,45 @@ .SetHttpGetSample("https://orthanc.uclouvain.be/demo/" + resources + "?since=0&limit=2", true); return; } - - ServerIndex& index = OrthancRestApi::GetIndex(call); - ServerContext& context = OrthancRestApi::GetContext(call); - - if (true) + + // TODO-FIND: include the FindRequest options parsing in a method (parse from get-arguments and from post payload) + // TODO-FIND: support other values for expand like expand=MainDicomTags,Labels,Parent,SeriesStatus + const bool expand = (call.HasArgument("expand") && + call.GetBooleanArgument("expand", true)); + + std::set requestedTags; + OrthancRestApi::GetRequestedTags(requestedTags, call); + + ResourceFinder finder(resourceType, expand); + finder.AddRequestedTags(requestedTags); + finder.SetFormat(OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); + + if (call.HasArgument("limit") || + call.HasArgument("since")) { - /** - * EXPERIMENTAL VERSION - **/ - - // TODO-FIND: include the FindRequest options parsing in a method (parse from get-arguments and from post payload) - // TODO-FIND: support other values for expand like expand=MainDicomTags,Labels,Parent,SeriesStatus - const bool expand = (call.HasArgument("expand") && - call.GetBooleanArgument("expand", true)); - - std::set requestedTags; - OrthancRestApi::GetRequestedTags(requestedTags, call); - - ResourceFinder finder(resourceType, expand); - finder.AddRequestedTags(requestedTags); - finder.SetFormat(OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); - - if (call.HasArgument("limit") || - call.HasArgument("since")) + if (!call.HasArgument("limit")) { - if (!call.HasArgument("limit")) - { - throw OrthancException(ErrorCode_BadRequest, - "Missing \"limit\" argument for GET request against: " + - call.FlattenUri()); - } - - if (!call.HasArgument("since")) - { - throw OrthancException(ErrorCode_BadRequest, - "Missing \"since\" argument for GET request against: " + - call.FlattenUri()); - } - - uint64_t since = boost::lexical_cast(call.GetArgument("since", "")); - uint64_t limit = boost::lexical_cast(call.GetArgument("limit", "")); - finder.SetLimitsSince(since); - finder.SetLimitsCount(limit); + throw OrthancException(ErrorCode_BadRequest, + "Missing \"limit\" argument for GET request against: " + + call.FlattenUri()); } - Json::Value answer; - finder.Execute(answer, context); - call.GetOutput().AnswerJson(answer); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - - std::list result; - - std::set requestedTags; - OrthancRestApi::GetRequestedTags(requestedTags, call); - - if (call.HasArgument("limit") || - call.HasArgument("since")) + if (!call.HasArgument("since")) { - if (!call.HasArgument("limit")) - { - throw OrthancException(ErrorCode_BadRequest, - "Missing \"limit\" argument for GET request against: " + - call.FlattenUri()); - } - - if (!call.HasArgument("since")) - { - throw OrthancException(ErrorCode_BadRequest, - "Missing \"since\" argument for GET request against: " + - call.FlattenUri()); - } - - size_t since = boost::lexical_cast(call.GetArgument("since", "")); - size_t limit = boost::lexical_cast(call.GetArgument("limit", "")); - index.GetAllUuids(result, resourceType, since, limit); + throw OrthancException(ErrorCode_BadRequest, + "Missing \"since\" argument for GET request against: " + + call.FlattenUri()); } - else - { - index.GetAllUuids(result, resourceType); - } - - AnswerListOfResources2(call.GetOutput(), context, result, resourceType, call.HasArgument("expand") && call.GetBooleanArgument("expand", true), - OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human), - requestedTags, - true /* allowStorageAccess */); + + uint64_t since = boost::lexical_cast(call.GetArgument("since", "")); + uint64_t limit = boost::lexical_cast(call.GetArgument("limit", "")); + finder.SetLimitsSince(since); + finder.SetLimitsCount(limit); } + + Json::Value answer; + finder.Execute(answer, OrthancRestApi::GetContext(call)); + call.GetOutput().AnswerJson(answer); } @@ -338,40 +215,18 @@ return; } - const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); - std::set requestedTags; OrthancRestApi::GetRequestedTags(requestedTags, call); - if (true) + ResourceFinder finder(resourceType, true /* expand */); + finder.AddRequestedTags(requestedTags); + finder.SetFormat(OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); + finder.SetOrthancId(resourceType, call.GetUriComponent("id", "")); + + Json::Value json; + if (finder.ExecuteOneResource(json, OrthancRestApi::GetContext(call))) { - /** - * EXPERIMENTAL VERSION - **/ - - ResourceFinder finder(resourceType, true /* expand */); - finder.AddRequestedTags(requestedTags); - finder.SetFormat(OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); - finder.SetOrthancId(resourceType, call.GetUriComponent("id", "")); - - Json::Value json; - if (finder.ExecuteOneResource(json, OrthancRestApi::GetContext(call))) - { - call.GetOutput().AnswerJson(json); - } - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - - Json::Value json; - if (OrthancRestApi::GetContext(call).ExpandResource( - json, call.GetUriComponent("id", ""), resourceType, format, requestedTags, true /* allowStorageAccess */)) - { - call.GetOutput().AnswerJson(json); - } + call.GetOutput().AnswerJson(json); } } @@ -3160,70 +3015,6 @@ } - namespace - { - class FindVisitor : public ServerContext::ILookupVisitor - { - private: - bool isComplete_; - std::list resources_; - FindStorageAccessMode findStorageAccessMode_; - - // cache the data we used during lookup and that we could reuse when building the answers - std::map instancesIds_; // the id of an instance for each found resource. - std::map > resourcesMainDicomTags_; // all tags read from DB for a resource (current level and upper levels) - std::map > resourcesDicomAsJson_; // the dicom-as-json for a resource - - DicomToJsonFormat format_; - - public: - explicit FindVisitor(DicomToJsonFormat format, FindStorageAccessMode findStorageAccessMode) : - isComplete_(false), - findStorageAccessMode_(findStorageAccessMode), - format_(format) - { - } - - virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE - { - return false; // (*) - } - - virtual void MarkAsComplete() ORTHANC_OVERRIDE - { - isComplete_ = true; // Unused information as of Orthanc 1.5.0 - } - - virtual void Visit(const std::string& publicId, - const std::string& instanceId, - const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson) ORTHANC_OVERRIDE - { - resources_.push_back(publicId); - instancesIds_[publicId] = instanceId; - resourcesMainDicomTags_[publicId].reset(mainDicomTags.Clone()); - if (dicomAsJson != NULL) - { - resourcesDicomAsJson_[publicId].reset(new Json::Value(*dicomAsJson)); // keep our own copy because we might reuse it between lookup and answers - } - else - { - resourcesDicomAsJson_[publicId] = boost::shared_ptr(); - } - } - - void Answer(RestApiOutput& output, - ServerContext& context, - ResourceType level, - bool expand, - const std::set& requestedTags) const - { - AnswerListOfResources1(output, context, resources_, instancesIds_, resourcesMainDicomTags_, resourcesDicomAsJson_, level, expand, format_, requestedTags, IsStorageAccessAllowedForAnswers(findStorageAccessMode_)); - } - }; - } - - static void Find(RestApiPostCall& call) { static const char* const KEY_CASE_SENSITIVE = "CaseSensitive"; @@ -3330,12 +3121,8 @@ throw OrthancException(ErrorCode_BadRequest, "Field \"" + std::string(KEY_LABELS_CONSTRAINT) + "\" must be an array of strings"); } - else if (true) + else { - /** - * EXPERIMENTAL VERSION - **/ - bool expand = false; if (request.isMember(KEY_EXPAND)) { @@ -3458,125 +3245,6 @@ finder.Execute(answer, context); call.GetOutput().AnswerJson(answer); } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - bool expand = false; - if (request.isMember(KEY_EXPAND)) - { - expand = request[KEY_EXPAND].asBool(); - } - - bool caseSensitive = false; - if (request.isMember(KEY_CASE_SENSITIVE)) - { - caseSensitive = request[KEY_CASE_SENSITIVE].asBool(); - } - - size_t limit = 0; - if (request.isMember(KEY_LIMIT)) - { - int tmp = request[KEY_LIMIT].asInt(); - if (tmp < 0) - { - throw OrthancException(ErrorCode_ParameterOutOfRange, - "Field \"" + std::string(KEY_LIMIT) + "\" must be a positive integer"); - } - - limit = static_cast(tmp); - } - - size_t since = 0; - if (request.isMember(KEY_SINCE)) - { - int tmp = request[KEY_SINCE].asInt(); - if (tmp < 0) - { - throw OrthancException(ErrorCode_ParameterOutOfRange, - "Field \"" + std::string(KEY_SINCE) + "\" must be a positive integer"); - } - - since = static_cast(tmp); - } - - std::set requestedTags; - - if (request.isMember(KEY_REQUESTED_TAGS)) - { - FromDcmtkBridge::ParseListOfTags(requestedTags, request[KEY_REQUESTED_TAGS]); - } - - ResourceType level = StringToResourceType(request[KEY_LEVEL].asCString()); - - DatabaseLookup query; - - Json::Value::Members members = request[KEY_QUERY].getMemberNames(); - for (size_t i = 0; i < members.size(); i++) - { - if (request[KEY_QUERY][members[i]].type() != Json::stringValue) - { - throw OrthancException(ErrorCode_BadRequest, - "Tag \"" + members[i] + "\" must be associated with a string"); - } - - const std::string value = request[KEY_QUERY][members[i]].asString(); - - if (!value.empty()) - { - // An empty string corresponds to an universal constraint, - // so we ignore it. This mimics the behavior of class - // "OrthancFindRequestHandler" - query.AddRestConstraint(FromDcmtkBridge::ParseTag(members[i]), - value, caseSensitive, true); - } - } - - std::set labels; - - if (request.isMember(KEY_LABELS)) // New in Orthanc 1.12.0 - { - for (Json::Value::ArrayIndex i = 0; i < request[KEY_LABELS].size(); i++) - { - if (request[KEY_LABELS][i].type() != Json::stringValue) - { - throw OrthancException(ErrorCode_BadRequest, "Field \"" + std::string(KEY_LABELS) + "\" must contain strings"); - } - else - { - labels.insert(request[KEY_LABELS][i].asString()); - } - } - } - - LabelsConstraint labelsConstraint = LabelsConstraint_All; - - if (request.isMember(KEY_LABELS_CONSTRAINT)) - { - const std::string& s = request[KEY_LABELS_CONSTRAINT].asString(); - if (s == "All") - { - labelsConstraint = LabelsConstraint_All; - } - else if (s == "Any") - { - labelsConstraint = LabelsConstraint_Any; - } - else if (s == "None") - { - labelsConstraint = LabelsConstraint_None; - } - else - { - throw OrthancException(ErrorCode_BadRequest, "Field \"" + std::string(KEY_LABELS_CONSTRAINT) + "\" must be \"All\", \"Any\", or \"None\""); - } - } - - FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human), context.GetFindStorageAccessMode()); - context.Apply(visitor, query, level, labels, labelsConstraint, since, limit); - visitor.Answer(call.GetOutput(), context, level, expand, requestedTags); - } } @@ -3604,9 +3272,6 @@ return; } - ServerIndex& index = OrthancRestApi::GetIndex(call); - ServerContext& context = OrthancRestApi::GetContext(call); - const bool expand = (!call.HasArgument("expand") || // this "expand" is the only one to have a false default value to keep backward compatibility call.GetBooleanArgument("expand", false)); @@ -3615,49 +3280,14 @@ std::set requestedTags; OrthancRestApi::GetRequestedTags(requestedTags, call); - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - - ResourceFinder finder(end, expand); - finder.SetOrthancId(start, call.GetUriComponent("id", "")); - finder.AddRequestedTags(requestedTags); - finder.SetFormat(format); - - Json::Value answer; - finder.Execute(answer, context); - call.GetOutput().AnswerJson(answer); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - std::list a, b, c; - a.push_back(call.GetUriComponent("id", "")); - - ResourceType type = start; - while (type != end) - { - b.clear(); - - for (std::list::const_iterator - it = a.begin(); it != a.end(); ++it) - { - index.GetChildren(c, *it); - b.splice(b.begin(), c); - } - - type = GetChildResourceType(type); - - a.clear(); - a.splice(a.begin(), b); - } - - AnswerListOfResources2(call.GetOutput(), context, a, type, expand, format, requestedTags, true /* allowStorageAccess */); - } + ResourceFinder finder(end, expand); + finder.SetOrthancId(start, call.GetUriComponent("id", "")); + finder.AddRequestedTags(requestedTags); + finder.SetFormat(format); + + Json::Value answer; + finder.Execute(answer, OrthancRestApi::GetContext(call)); + call.GetOutput().AnswerJson(answer); } diff -r eb56ee3c5d63 -r 1404a80dd461 OrthancServer/Sources/OrthancWebDav.cpp --- a/OrthancServer/Sources/OrthancWebDav.cpp Fri Jul 12 17:51:52 2024 +0200 +++ b/OrthancServer/Sources/OrthancWebDav.cpp Fri Jul 12 17:54:29 2024 +0200 @@ -86,99 +86,6 @@ } - class OrthancWebDav::DicomIdentifiersVisitor : public ServerContext::ILookupVisitor - { - private: - ServerContext& context_; - bool isComplete_; - Collection& target_; - ResourceType level_; - - public: - DicomIdentifiersVisitor(ServerContext& context, - Collection& target, - ResourceType level) : - context_(context), - isComplete_(false), - target_(target), - level_(level) - { - } - - virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE - { - return false; // (*) - } - - virtual void MarkAsComplete() ORTHANC_OVERRIDE - { - isComplete_ = true; // TODO - } - - virtual void Visit(const std::string& publicId, - const std::string& instanceId /* unused */, - const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE - { - DicomTag tag(0, 0); - MetadataType timeMetadata; - - switch (level_) - { - case ResourceType_Study: - tag = DICOM_TAG_STUDY_INSTANCE_UID; - timeMetadata = MetadataType_LastUpdate; - break; - - case ResourceType_Series: - tag = DICOM_TAG_SERIES_INSTANCE_UID; - timeMetadata = MetadataType_LastUpdate; - break; - - case ResourceType_Instance: - tag = DICOM_TAG_SOP_INSTANCE_UID; - timeMetadata = MetadataType_Instance_ReceptionDate; - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - - std::string s; - if (mainDicomTags.LookupStringValue(s, tag, false) && - !s.empty()) - { - std::unique_ptr resource; - - if (level_ == ResourceType_Instance) - { - FileInfo info; - int64_t revision; // Ignored - if (context_.GetIndex().LookupAttachment(info, revision, publicId, FileContentType_Dicom)) - { - std::unique_ptr f(new File(s + ".dcm")); - f->SetMimeType(MimeType_Dicom); - f->SetContentLength(info.GetUncompressedSize()); - resource.reset(f.release()); - } - } - else - { - resource.reset(new Folder(s)); - } - - if (resource.get() != NULL) - { - boost::posix_time::ptime t; - LookupTime(t, context_, publicId, level_, timeMetadata); - resource->SetCreationTime(t); - target_.AddResource(resource.release()); - } - } - } - }; - - class OrthancWebDav::DicomIdentifiersVisitorV2 : public ResourceFinder::IVisitor { private: @@ -271,58 +178,6 @@ }; - class OrthancWebDav::DicomFileVisitor : public ServerContext::ILookupVisitor - { - private: - ServerContext& context_; - bool success_; - std::string& target_; - boost::posix_time::ptime& time_; - - public: - DicomFileVisitor(ServerContext& context, - std::string& target, - boost::posix_time::ptime& time) : - context_(context), - success_(false), - target_(target), - time_(time) - { - } - - bool IsSuccess() const - { - return success_; - } - - virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE - { - return false; // (*) - } - - virtual void MarkAsComplete() ORTHANC_OVERRIDE - { - } - - virtual void Visit(const std::string& publicId, - const std::string& instanceId /* unused */, - const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE - { - if (success_) - { - success_ = false; // Two matches => Error - } - else - { - LookupTime(time_, context_, publicId, ResourceType_Instance, MetadataType_Instance_ReceptionDate); - context_.ReadDicom(target_, publicId); - success_ = true; - } - } - }; - - class OrthancWebDav::DicomFileVisitorV2 : public ResourceFinder::IVisitor { private: @@ -1569,12 +1424,11 @@ { DatabaseLookup query; ResourceType level; - size_t limit = 0; // By default, no limits if (path.size() == 1) { level = ResourceType_Study; - limit = 0; // TODO - Should we limit here? + // TODO - Should we limit here? } else if (path.size() == 2) { @@ -1599,47 +1453,31 @@ return false; } - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - - ResourceFinder finder(level, false /* don't expand */); - finder.SetDatabaseLookup(query); - finder.SetRetrieveMetadata(true); + ResourceFinder finder(level, false /* don't expand */); + finder.SetDatabaseLookup(query); + finder.SetRetrieveMetadata(true); - switch (level) - { - case ResourceType_Study: - finder.AddRequestedTag(DICOM_TAG_STUDY_INSTANCE_UID); - break; - - case ResourceType_Series: - finder.AddRequestedTag(DICOM_TAG_SERIES_INSTANCE_UID); - break; + switch (level) + { + case ResourceType_Study: + finder.AddRequestedTag(DICOM_TAG_STUDY_INSTANCE_UID); + break; - case ResourceType_Instance: - finder.AddRequestedTag(DICOM_TAG_SOP_INSTANCE_UID); - finder.SetRetrieveAttachments(true); - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } + case ResourceType_Series: + finder.AddRequestedTag(DICOM_TAG_SERIES_INSTANCE_UID); + break; - DicomIdentifiersVisitorV2 visitor(collection); - finder.Execute(visitor, context_); + case ResourceType_Instance: + finder.AddRequestedTag(DICOM_TAG_SOP_INSTANCE_UID); + finder.SetRetrieveAttachments(true); + break; + + default: + throw OrthancException(ErrorCode_InternalError); } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - DicomIdentifiersVisitor visitor(context_, collection, level); - context_.Apply(visitor, query, level, 0 /* since */, limit); - } + DicomIdentifiersVisitorV2 visitor(collection); + finder.Execute(visitor, context_); return true; } @@ -1707,23 +1545,7 @@ true /* case sensitive */, true /* mandatory tag */); mime = MimeType_Json; - - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - return GetOrthancJson(content, context_, ResourceType_Study, query); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - OrthancJsonVisitor visitor(context_, content, ResourceType_Study); - context_.Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); - return visitor.IsSuccess(); - } + return GetOrthancJson(content, context_, ResourceType_Study, query); } else if (path.size() == 4 && path[3] == SERIES_INFO) @@ -1735,23 +1557,7 @@ true /* case sensitive */, true /* mandatory tag */); mime = MimeType_Json; - - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - return GetOrthancJson(content, context_, ResourceType_Series, query); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - OrthancJsonVisitor visitor(context_, content, ResourceType_Series); - context_.Apply(visitor, query, ResourceType_Series, 0 /* since */, 0 /* no limit */); - return visitor.IsSuccess(); - } + return GetOrthancJson(content, context_, ResourceType_Series, query); } else if (path.size() == 4 && boost::ends_with(path[3], ".dcm")) @@ -1768,30 +1574,15 @@ mime = MimeType_Dicom; - if (true) - { - /** - * EXPERIMENTAL VERSION - **/ - ResourceFinder finder(ResourceType_Instance, false /* no expand */); - finder.SetDatabaseLookup(query); - finder.SetRetrieveMetadata(true); - finder.SetRetrieveAttachments(true); + ResourceFinder finder(ResourceType_Instance, false /* no expand */); + finder.SetDatabaseLookup(query); + finder.SetRetrieveMetadata(true); + finder.SetRetrieveAttachments(true); - DicomFileVisitorV2 visitor(context_, content, modificationTime); - finder.Execute(visitor, context_); + DicomFileVisitorV2 visitor(context_, content, modificationTime); + finder.Execute(visitor, context_); - return visitor.IsSuccess(); - } - else - { - /** - * VERSION IN ORTHANC <= 1.12.4 - **/ - DicomFileVisitor visitor(context_, content, modificationTime); - context_.Apply(visitor, query, ResourceType_Instance, 0 /* since */, 0 /* no limit */); - return visitor.IsSuccess(); - } + return visitor.IsSuccess(); } else { diff -r eb56ee3c5d63 -r 1404a80dd461 OrthancServer/Sources/OrthancWebDav.h --- a/OrthancServer/Sources/OrthancWebDav.h Fri Jul 12 17:51:52 2024 +0200 +++ b/OrthancServer/Sources/OrthancWebDav.h Fri Jul 12 17:54:29 2024 +0200 @@ -38,9 +38,7 @@ typedef std::map Templates; class DicomDeleteVisitor; - class DicomFileVisitor; class DicomFileVisitorV2; - class DicomIdentifiersVisitor; class DicomIdentifiersVisitorV2; class InstancesOfSeries; class InternalNode;