# HG changeset patch # User Sebastien Jodogne # Date 1544549798 -3600 # Node ID 7695a9c810994430621fbd5a33ec268a89067e49 # Parent 0a52af0c66e7709f3bef99b5ab36cb9a19da3977 refactoring /tools/find using LookupResource::IVisitor diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/OrthancFindRequestHandler.cpp --- a/OrthancServer/OrthancFindRequestHandler.cpp Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/OrthancFindRequestHandler.cpp Tue Dec 11 18:36:38 2018 +0100 @@ -623,8 +623,6 @@ if (FilterQueryTag(value, level, tag, manufacturer)) { - // TODO - Move this to "ResourceLookup::AddDicomConstraint()" - ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(tag); // DICOM specifies that searches must be case sensitive, except diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Tue Dec 11 18:36:38 2018 +0100 @@ -1269,6 +1269,42 @@ } + namespace + { + class FindVisitor : public LookupResource::IVisitor + { + private: + bool isComplete_; + std::list resources_; + + public: + FindVisitor() : + isComplete_(false) + { + } + + virtual void MarkAsComplete() + { + isComplete_ = true; // Unused information as of Orthanc 1.5.0 + } + + virtual void Visit(const std::string& publicId, + const Json::Value& dicom) + { + resources_.push_back(publicId); + } + + void Answer(RestApiOutput& output, + ServerIndex& index, + ResourceType level, + bool expand) const + { + AnswerListOfResources(output, index, resources_, level, expand); + } + }; + } + + static void Find(RestApiPostCall& call) { static const char* const KEY_CASE_SENSITIVE = "CaseSensitive"; @@ -1281,15 +1317,43 @@ ServerContext& context = OrthancRestApi::GetContext(call); Json::Value request; - if (call.ParseJsonRequest(request) && - request.type() == Json::objectValue && - request.isMember(KEY_LEVEL) && - request.isMember(KEY_QUERY) && - request[KEY_LEVEL].type() == Json::stringValue && - request[KEY_QUERY].type() == Json::objectValue && - (!request.isMember(KEY_CASE_SENSITIVE) || request[KEY_CASE_SENSITIVE].type() == Json::booleanValue) && - (!request.isMember(KEY_LIMIT) || request[KEY_LIMIT].type() == Json::intValue) && - (!request.isMember(KEY_SINCE) || request[KEY_SINCE].type() == Json::intValue)) + if (!call.ParseJsonRequest(request) || + request.type() != Json::objectValue) + { + throw OrthancException(ErrorCode_BadRequest, + "The body must contain a JSON object"); + } + else if (!request.isMember(KEY_LEVEL) || + request[KEY_LEVEL].type() != Json::stringValue) + { + throw OrthancException(ErrorCode_BadRequest, + "Field \"" + std::string(KEY_LEVEL) + "\" is missing, or should be a string"); + } + else if (!request.isMember(KEY_QUERY) && + request[KEY_QUERY].type() != Json::objectValue) + { + throw OrthancException(ErrorCode_BadRequest, + "Field \"" + std::string(KEY_QUERY) + "\" is missing, or should be a JSON object"); + } + else if (request.isMember(KEY_CASE_SENSITIVE) && + request[KEY_CASE_SENSITIVE].type() != Json::booleanValue) + { + throw OrthancException(ErrorCode_BadRequest, + "Field \"" + std::string(KEY_CASE_SENSITIVE) + "\" should be a Boolean"); + } + else if (request.isMember(KEY_LIMIT) && + request[KEY_LIMIT].type() != Json::intValue) + { + throw OrthancException(ErrorCode_BadRequest, + "Field \"" + std::string(KEY_LIMIT) + "\" should be an integer"); + } + else if (request.isMember(KEY_SINCE) && + request[KEY_SINCE].type() != Json::intValue) + { + throw OrthancException(ErrorCode_BadRequest, + "Field \"" + std::string(KEY_SINCE) + "\" should be an integer"); + } + else { bool expand = false; if (request.isMember(KEY_EXPAND)) @@ -1309,7 +1373,8 @@ int tmp = request[KEY_LIMIT].asInt(); if (tmp < 0) { - throw OrthancException(ErrorCode_ParameterOutOfRange); + throw OrthancException(ErrorCode_ParameterOutOfRange, + "Field \"" + std::string(KEY_LIMIT) + "\" should be a positive integer"); } limit = static_cast(tmp); @@ -1321,7 +1386,8 @@ int tmp = request[KEY_SINCE].asInt(); if (tmp < 0) { - throw OrthancException(ErrorCode_ParameterOutOfRange); + throw OrthancException(ErrorCode_ParameterOutOfRange, + "Field \"" + std::string(KEY_SINCE) + "\" should be a positive integer"); } since = static_cast(tmp); @@ -1336,7 +1402,8 @@ { if (request[KEY_QUERY][members[i]].type() != Json::stringValue) { - throw OrthancException(ErrorCode_BadRequest); + throw OrthancException(ErrorCode_BadRequest, + "Tag \"" + members[i] + "\" should be associated with a string"); } query.AddDicomConstraint(FromDcmtkBridge::ParseTag(members[i]), @@ -1344,15 +1411,9 @@ caseSensitive); } - bool isComplete; - std::list resources; - context.Apply(isComplete, resources, query, since, limit); - AnswerListOfResources(call.GetOutput(), context.GetIndex(), - resources, query.GetLevel(), expand); - } - else - { - throw OrthancException(ErrorCode_BadRequest); + FindVisitor visitor; + context.Apply(visitor, query, since, limit); + visitor.Answer(call.GetOutput(), context.GetIndex(), query.GetLevel(), expand); } } diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/Search/LookupIdentifierQuery.cpp --- a/OrthancServer/Search/LookupIdentifierQuery.cpp Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/Search/LookupIdentifierQuery.cpp Tue Dec 11 18:36:38 2018 +0100 @@ -34,9 +34,10 @@ #include "../PrecompiledHeadersServer.h" #include "LookupIdentifierQuery.h" +#include "../../Core/DicomParsing/FromDcmtkBridge.h" #include "../../Core/OrthancException.h" +#include "../ServerToolbox.h" #include "SetOfResources.h" -#include "../../Core/DicomParsing/FromDcmtkBridge.h" #include @@ -44,6 +45,28 @@ namespace Orthanc { + LookupIdentifierQuery::SingleConstraint:: + SingleConstraint(const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value) : + tag_(tag), + type_(type), + value_(ServerToolbox::NormalizeIdentifier(value)) + { + } + + + LookupIdentifierQuery::RangeConstraint:: + RangeConstraint(const DicomTag& tag, + const std::string& start, + const std::string& end) : + tag_(tag), + start_(ServerToolbox::NormalizeIdentifier(start)), + end_(ServerToolbox::NormalizeIdentifier(end)) + { + } + + LookupIdentifierQuery::Disjunction::~Disjunction() { for (size_t i = 0; i < singleConstraints_.size(); i++) @@ -84,6 +107,12 @@ } + bool LookupIdentifierQuery::IsIdentifier(const DicomTag& tag) + { + return ServerToolbox::IsIdentifier(tag, level_); + } + + void LookupIdentifierQuery::AddConstraint(DicomTag tag, IdentifierConstraintType type, const std::string& value) diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/Search/LookupIdentifierQuery.h --- a/OrthancServer/Search/LookupIdentifierQuery.h Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/Search/LookupIdentifierQuery.h Tue Dec 11 18:36:38 2018 +0100 @@ -33,7 +33,6 @@ #pragma once -#include "../ServerToolbox.h" #include "../IDatabaseWrapper.h" #include "SetOfResources.h" @@ -79,12 +78,7 @@ public: SingleConstraint(const DicomTag& tag, IdentifierConstraintType type, - const std::string& value) : - tag_(tag), - type_(type), - value_(ServerToolbox::NormalizeIdentifier(value)) - { - } + const std::string& value); const DicomTag& GetTag() const { @@ -113,12 +107,7 @@ public: RangeConstraint(const DicomTag& tag, const std::string& start, - const std::string& end) : - tag_(tag), - start_(ServerToolbox::NormalizeIdentifier(start)), - end_(ServerToolbox::NormalizeIdentifier(end)) - { - } + const std::string& end); const DicomTag& GetTag() const { @@ -189,10 +178,7 @@ ~LookupIdentifierQuery(); - bool IsIdentifier(const DicomTag& tag) - { - return ServerToolbox::IsIdentifier(tag, level_); - } + bool IsIdentifier(const DicomTag& tag); void AddConstraint(DicomTag tag, IdentifierConstraintType type, diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/Search/LookupResource.h --- a/OrthancServer/Search/LookupResource.h Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/Search/LookupResource.h Tue Dec 11 18:36:38 2018 +0100 @@ -82,6 +82,19 @@ IDatabaseWrapper& database) const; public: + class IVisitor : public boost::noncopyable + { + public: + virtual ~IVisitor() + { + } + + virtual void MarkAsComplete() = 0; + + virtual void Visit(const std::string& publicId, + const Json::Value& dicom) = 0; + }; + LookupResource(ResourceType level); ~LookupResource(); diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/ServerContext.cpp Tue Dec 11 18:36:38 2018 +0100 @@ -773,21 +773,19 @@ } - void ServerContext::Apply(bool& isComplete, - std::list& result, + void ServerContext::Apply(LookupResource::IVisitor& visitor, const ::Orthanc::LookupResource& lookup, size_t since, size_t limit) { - result.clear(); - isComplete = true; - std::vector resources, instances; GetIndex().FindCandidates(resources, instances, lookup); assert(resources.size() == instances.size()); + size_t countResults = 0; size_t skipped = 0; + for (size_t i = 0; i < instances.size(); i++) { // TODO - Don't read the full JSON from the disk if only "main @@ -802,17 +800,19 @@ skipped++; } else if (limit != 0 && - result.size() >= limit) + countResults >= limit) { - isComplete = false; - return; // too many results + return; // too many results, don't mark as complete } else { - result.push_back(resources[i]); + visitor.Visit(resources[i], dicom); + countResults ++; } } } + + visitor.MarkAsComplete(); } diff -r 0a52af0c66e7 -r 7695a9c81099 OrthancServer/ServerContext.h --- a/OrthancServer/ServerContext.h Tue Dec 11 13:21:34 2018 +0100 +++ b/OrthancServer/ServerContext.h Tue Dec 11 18:36:38 2018 +0100 @@ -38,6 +38,7 @@ #include "LuaScripting.h" #include "OrthancHttpHandler.h" #include "ServerIndex.h" +#include "Search/LookupResource.h" #include "../Core/Cache/MemoryCache.h" #include "../Core/Cache/SharedArchive.h" @@ -334,8 +335,7 @@ void Stop(); - void Apply(bool& isComplete, - std::list& result, + void Apply(LookupResource::IVisitor& visitor, const ::Orthanc::LookupResource& lookup, size_t since, size_t limit); diff -r 0a52af0c66e7 -r 7695a9c81099 UnitTestsSources/ServerIndexTests.cpp --- a/UnitTestsSources/ServerIndexTests.cpp Tue Dec 11 13:21:34 2018 +0100 +++ b/UnitTestsSources/ServerIndexTests.cpp Tue Dec 11 18:36:38 2018 +0100 @@ -38,9 +38,10 @@ #include "../Core/FileStorage/MemoryStorageArea.h" #include "../Core/Logging.h" #include "../OrthancServer/DatabaseWrapper.h" +#include "../OrthancServer/Search/LookupIdentifierQuery.h" #include "../OrthancServer/ServerContext.h" #include "../OrthancServer/ServerIndex.h" -#include "../OrthancServer/Search/LookupIdentifierQuery.h" +#include "../OrthancServer/ServerToolbox.h" #include #include