# HG changeset patch # User Sebastien Jodogne # Date 1715248796 -7200 # Node ID 4640b7ae9a11cb77c9cd6d43e613a1c8e701b770 # Parent f1ce8dd361b75bd9e7d24806fe5a422368138b56 moving normalization of constraints into FindRequest diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/CMakeLists.txt --- a/OrthancServer/CMakeLists.txt Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/CMakeLists.txt Thu May 09 11:59:56 2024 +0200 @@ -97,6 +97,7 @@ ${CMAKE_SOURCE_DIR}/Sources/Database/Compatibility/SetOfResources.cpp ${CMAKE_SOURCE_DIR}/Sources/Database/FindRequest.cpp ${CMAKE_SOURCE_DIR}/Sources/Database/FindResponse.cpp + ${CMAKE_SOURCE_DIR}/Sources/Database/MainDicomTagsRegistry.cpp ${CMAKE_SOURCE_DIR}/Sources/Database/OrthancIdentifiers.cpp ${CMAKE_SOURCE_DIR}/Sources/Database/ResourcesContent.cpp ${CMAKE_SOURCE_DIR}/Sources/Database/SQLiteDatabaseWrapper.cpp diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Thu May 09 11:59:56 2024 +0200 @@ -1279,8 +1279,7 @@ virtual void ExecuteFind(FindResponse& response, - const FindRequest& request, - const std::vector& normalized) ORTHANC_OVERRIDE + const FindRequest& request) ORTHANC_OVERRIDE { // TODO-FIND throw OrthancException(ErrorCode_NotImplemented); @@ -1288,12 +1287,11 @@ virtual void ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) ORTHANC_OVERRIDE + const FindRequest& request) ORTHANC_OVERRIDE { // TODO-FIND Compatibility::GenericFind find(*this); - find.ExecuteFind(identifiers, request, normalized); + find.ExecuteFind(identifiers, request); } diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/BaseDatabaseWrapper.cpp --- a/OrthancServer/Sources/Database/BaseDatabaseWrapper.cpp Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/BaseDatabaseWrapper.cpp Thu May 09 11:59:56 2024 +0200 @@ -47,19 +47,17 @@ void BaseDatabaseWrapper::BaseTransaction::ExecuteFind(FindResponse& response, - const FindRequest& request, - const std::vector& normalized) + const FindRequest& request) { throw OrthancException(ErrorCode_NotImplemented); // Not supported } void BaseDatabaseWrapper::BaseTransaction::ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) + const FindRequest& request) { Compatibility::GenericFind find(*this); - find.ExecuteFind(identifiers, request, normalized); + find.ExecuteFind(identifiers, request); } diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/BaseDatabaseWrapper.h --- a/OrthancServer/Sources/Database/BaseDatabaseWrapper.h Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/BaseDatabaseWrapper.h Thu May 09 11:59:56 2024 +0200 @@ -48,12 +48,10 @@ int64_t& uncompressedSize) ORTHANC_OVERRIDE; virtual void ExecuteFind(FindResponse& response, - const FindRequest& request, - const std::vector& normalized) ORTHANC_OVERRIDE; + const FindRequest& request) ORTHANC_OVERRIDE; virtual void ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) ORTHANC_OVERRIDE; + const FindRequest& request) ORTHANC_OVERRIDE; virtual void ExecuteExpand(FindResponse& response, const FindRequest& request, diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/Compatibility/GenericFind.cpp --- a/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Thu May 09 11:59:56 2024 +0200 @@ -33,8 +33,7 @@ namespace Compatibility { void GenericFind::ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) + const FindRequest& request) { if (!request.GetOrthancIdentifiers().HasPatientId() && !request.GetOrthancIdentifiers().HasStudyId() && diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/Compatibility/GenericFind.h --- a/OrthancServer/Sources/Database/Compatibility/GenericFind.h Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.h Thu May 09 11:59:56 2024 +0200 @@ -44,8 +44,7 @@ } void ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized); + const FindRequest& request); void ExecuteExpand(FindResponse& response, const FindRequest& request, diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/FindRequest.cpp --- a/OrthancServer/Sources/Database/FindRequest.cpp Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/FindRequest.cpp Thu May 09 11:59:56 2024 +0200 @@ -24,9 +24,11 @@ #include "../../../OrthancFramework/Sources/OrthancException.h" +#include "MainDicomTagsRegistry.h" #include + namespace Orthanc { FindRequest::FindRequest(ResourceType level) : @@ -139,10 +141,35 @@ void FindRequest::AddDicomTagConstraint(const DicomTagConstraint& constraint) { - dicomTagConstraints_.push_back(constraint); + // This behaves like "StatelessDatabaseOperations::NormalizeLookup()" in Orthanc <= 1.12.3 + + if (mainDicomTagsRegistry_.get() == NULL) + { + // Lazy creation of the registry of main DICOM tags + mainDicomTagsRegistry_.reset(new MainDicomTagsRegistry()); + } + + ResourceType level; + DicomTagType type; + + mainDicomTagsRegistry_->LookupTag(level, type, constraint.GetTag()); + + if (type == DicomTagType_Identifier || + type == DicomTagType_Main) + { + // Use the fact that patient-level tags are copied at the study level + if (level == ResourceType_Patient && + GetLevel() != ResourceType_Patient) + { + level = ResourceType_Study; + } + + dicomTagConstraints_.push_back(constraint.ConvertToDatabaseConstraint(level, type)); + } } - const DicomTagConstraint& FindRequest::GetDicomTagConstraint(size_t index) const + + const DatabaseConstraint& FindRequest::GetDicomTagConstraint(size_t index) const { if (index >= dicomTagConstraints_.size()) { diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/FindRequest.h --- a/OrthancServer/Sources/Database/FindRequest.h Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/FindRequest.h Thu May 09 11:59:56 2024 +0200 @@ -37,6 +37,8 @@ namespace Orthanc { + class MainDicomTagsRegistry; + class FindRequest : public boost::noncopyable { public: @@ -153,11 +155,10 @@ private: - // filter & ordering fields ResourceType level_; // The level of the response (the filtering on tags, labels and metadata also happens at this level) OrthancIdentifiers orthancIdentifiers_; // The response must belong to this Orthanc resources hierarchy - std::vector dicomTagConstraints_; // All tags filters (note: the order is not important) + std::deque dicomTagConstraints_; // All tags filters (note: the order is not important) std::deque /* TODO-FIND */ metadataConstraints_; // All metadata filters (note: the order is not important) bool hasLimits_; uint64_t limitsSince_; @@ -181,6 +182,8 @@ std::set retrieveChildrenMetadata_; bool retrieveOneInstanceIdentifier_; + std::unique_ptr mainDicomTagsRegistry_; + public: explicit FindRequest(ResourceType level); @@ -214,13 +217,13 @@ return dicomTagConstraints_.size(); } + const DatabaseConstraint& GetDicomTagConstraint(size_t index) const; + size_t GetMetadataConstraintsCount() const { return metadataConstraints_.size(); } - const DicomTagConstraint& GetDicomTagConstraint(size_t index) const; - void SetLimits(uint64_t since, uint64_t count); diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/IDatabaseWrapper.h --- a/OrthancServer/Sources/Database/IDatabaseWrapper.h Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h Thu May 09 11:59:56 2024 +0200 @@ -359,13 +359,11 @@ // This is only implemented if "HasIntegratedFind()" is "true" virtual void ExecuteFind(FindResponse& response, - const FindRequest& request, - const std::vector& normalized) = 0; + const FindRequest& request) = 0; // This is only implemented if "HasIntegratedFind()" is "false" virtual void ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) = 0; + const FindRequest& request) = 0; /** * This is only implemented if "HasIntegratedFind()" is diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp Thu May 09 11:59:56 2024 +0200 @@ -0,0 +1,98 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2024 Osimis S.A., Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "../PrecompiledHeadersServer.h" +#include "MainDicomTagsRegistry.h" + +#include "../ServerToolbox.h" + +namespace Orthanc +{ + void MainDicomTagsRegistry::LoadTags(ResourceType level) + { + { + const DicomTag* tags = NULL; + size_t size; + + ServerToolbox::LoadIdentifiers(tags, size, level); + + for (size_t i = 0; i < size; i++) + { + if (registry_.find(tags[i]) == registry_.end()) + { + registry_[tags[i]] = TagInfo(level, DicomTagType_Identifier); + } + else + { + // These patient-level tags are copied in the study level + assert(level == ResourceType_Study && + (tags[i] == DICOM_TAG_PATIENT_ID || + tags[i] == DICOM_TAG_PATIENT_NAME || + tags[i] == DICOM_TAG_PATIENT_BIRTH_DATE)); + } + } + } + + { + std::set tags; + DicomMap::GetMainDicomTags(tags, level); + + for (std::set::const_iterator + tag = tags.begin(); tag != tags.end(); ++tag) + { + if (registry_.find(*tag) == registry_.end()) + { + registry_[*tag] = TagInfo(level, DicomTagType_Main); + } + } + } + } + + + MainDicomTagsRegistry::MainDicomTagsRegistry() + { + LoadTags(ResourceType_Patient); + LoadTags(ResourceType_Study); + LoadTags(ResourceType_Series); + LoadTags(ResourceType_Instance); + } + + + void MainDicomTagsRegistry::LookupTag(ResourceType& level, + DicomTagType& type, + const DicomTag& tag) const + { + Registry::const_iterator it = registry_.find(tag); + + if (it == registry_.end()) + { + // Default values + level = ResourceType_Instance; + type = DicomTagType_Generic; + } + else + { + level = it->second.GetLevel(); + type = it->second.GetType(); + } + } +} diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/MainDicomTagsRegistry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Sources/Database/MainDicomTagsRegistry.h Thu May 09 11:59:56 2024 +0200 @@ -0,0 +1,77 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2024 Osimis S.A., Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Search/DicomTagConstraint.h" + +#include + + +namespace Orthanc +{ + class MainDicomTagsRegistry : public boost::noncopyable + { + private: + class TagInfo + { + private: + ResourceType level_; + DicomTagType type_; + + public: + TagInfo() + { + } + + TagInfo(ResourceType level, + DicomTagType type) : + level_(level), + type_(type) + { + } + + ResourceType GetLevel() const + { + return level_; + } + + DicomTagType GetType() const + { + return type_; + } + }; + + typedef std::map Registry; + + Registry registry_; + + void LoadTags(ResourceType level); + + public: + MainDicomTagsRegistry(); + + void LookupTag(ResourceType& level, + DicomTagType& type, + const DicomTag& tag) const; + }; +} diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu May 09 11:59:56 2024 +0200 @@ -299,113 +299,6 @@ } - class StatelessDatabaseOperations::MainDicomTagsRegistry : public boost::noncopyable - { - private: - class TagInfo - { - private: - ResourceType level_; - DicomTagType type_; - - public: - TagInfo() - { - } - - TagInfo(ResourceType level, - DicomTagType type) : - level_(level), - type_(type) - { - } - - ResourceType GetLevel() const - { - return level_; - } - - DicomTagType GetType() const - { - return type_; - } - }; - - typedef std::map Registry; - - - Registry registry_; - - void LoadTags(ResourceType level) - { - { - const DicomTag* tags = NULL; - size_t size; - - ServerToolbox::LoadIdentifiers(tags, size, level); - - for (size_t i = 0; i < size; i++) - { - if (registry_.find(tags[i]) == registry_.end()) - { - registry_[tags[i]] = TagInfo(level, DicomTagType_Identifier); - } - else - { - // These patient-level tags are copied in the study level - assert(level == ResourceType_Study && - (tags[i] == DICOM_TAG_PATIENT_ID || - tags[i] == DICOM_TAG_PATIENT_NAME || - tags[i] == DICOM_TAG_PATIENT_BIRTH_DATE)); - } - } - } - - { - std::set tags; - DicomMap::GetMainDicomTags(tags, level); - - for (std::set::const_iterator - tag = tags.begin(); tag != tags.end(); ++tag) - { - if (registry_.find(*tag) == registry_.end()) - { - registry_[*tag] = TagInfo(level, DicomTagType_Main); - } - } - } - } - - public: - MainDicomTagsRegistry() - { - LoadTags(ResourceType_Patient); - LoadTags(ResourceType_Study); - LoadTags(ResourceType_Series); - LoadTags(ResourceType_Instance); - } - - void LookupTag(ResourceType& level, - DicomTagType& type, - const DicomTag& tag) const - { - Registry::const_iterator it = registry_.find(tag); - - if (it == registry_.end()) - { - // Default values - level = ResourceType_Instance; - type = DicomTagType_Generic; - } - else - { - level = it->second.GetLevel(); - type = it->second.GetType(); - } - } - }; - - void StatelessDatabaseOperations::ReadWriteTransaction::LogChange(int64_t internalId, ChangeType changeType, ResourceType resourceType, @@ -501,38 +394,6 @@ } } - void StatelessDatabaseOperations::NormalizeLookup(std::vector& target, - const FindRequest& findRequest) const - { - assert(mainDicomTagsRegistry_.get() != NULL); - - target.clear(); - target.reserve(findRequest.GetDicomTagConstraintsCount()); - - for (size_t i = 0; i < findRequest.GetDicomTagConstraintsCount(); i++) - { - ResourceType level; - DicomTagType type; - - mainDicomTagsRegistry_->LookupTag(level, type, findRequest.GetDicomTagConstraint(i).GetTag()); - - if (type == DicomTagType_Identifier || - type == DicomTagType_Main) - { - // Use the fact that patient-level tags are copied at the study level - if (level == ResourceType_Patient && - findRequest.GetLevel() != ResourceType_Patient) - { - level = ResourceType_Study; - } - - target.push_back(findRequest.GetDicomTagConstraint(i).ConvertToDatabaseConstraint(level, type)); - } - } - - // TODO-FIND: add metadata constraints - } - class StatelessDatabaseOperations::Transaction : public boost::noncopyable { @@ -3844,23 +3705,23 @@ void StatelessDatabaseOperations::ExecuteFind(FindResponse& response, const FindRequest& request) { - class IntegratedFind : public ReadOnlyOperationsT3&> + class IntegratedFind : public ReadOnlyOperationsT2 { public: virtual void ApplyTuple(ReadOnlyTransaction& transaction, const Tuple& tuple) ORTHANC_OVERRIDE { - transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); + transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>()); } }; - class FindStage : public ReadOnlyOperationsT3&, const FindRequest&, const std::vector&> + class FindStage : public ReadOnlyOperationsT2&, const FindRequest&> { public: virtual void ApplyTuple(ReadOnlyTransaction& transaction, const Tuple& tuple) ORTHANC_OVERRIDE { - transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); + transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>()); } }; @@ -3874,9 +3735,6 @@ } }; - std::vector normalized; - NormalizeLookup(normalized, request); - if (db_.HasIntegratedFind()) { /** @@ -3884,7 +3742,7 @@ * executed in one single transaction. **/ IntegratedFind operations; - operations.Apply(*this, response, request, normalized); + operations.Apply(*this, response, request); } else { @@ -3896,7 +3754,7 @@ std::list identifiers; FindStage find; - find.Apply(*this, identifiers, request, normalized); + find.Apply(*this, identifiers, request); ExpandStage expand; diff -r f1ce8dd361b7 -r 4640b7ae9a11 OrthancServer/Sources/Database/StatelessDatabaseOperations.h --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Thu May 09 11:32:06 2024 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Thu May 09 11:59:56 2024 +0200 @@ -24,8 +24,9 @@ #include "../../../OrthancFramework/Sources/DicomFormat/DicomMap.h" +#include "../DicomInstanceOrigin.h" #include "IDatabaseWrapper.h" -#include "../DicomInstanceOrigin.h" +#include "MainDicomTagsRegistry.h" #include #include @@ -393,17 +394,15 @@ } void ExecuteFind(FindResponse& response, - const FindRequest& request, - const std::vector& normalized) + const FindRequest& request) { - transaction_.ExecuteFind(response, request, normalized); + transaction_.ExecuteFind(response, request); } void ExecuteFind(std::list& identifiers, - const FindRequest& request, - const std::vector& normalized) + const FindRequest& request) { - transaction_.ExecuteFind(identifiers, request, normalized); + transaction_.ExecuteFind(identifiers, request); } void ExecuteExpand(FindResponse& response, @@ -579,7 +578,6 @@ private: - class MainDicomTagsRegistry; class Transaction; IDatabaseWrapper& db_; @@ -594,9 +592,6 @@ const DatabaseLookup& source, ResourceType level) const; - void NormalizeLookup(std::vector& target, - const FindRequest& findRequest) const; - void ApplyInternal(IReadOnlyOperations* readOperations, IReadWriteOperations* writeOperations);