Mercurial > hg > orthanc
changeset 1746:d143db00a794 db-changes
SetOfResources
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 26 Oct 2015 16:04:58 +0100 |
parents | 38dda23c7d7d |
children | ca69082ab200 |
files | CMakeLists.txt Core/Enumerations.cpp Core/Enumerations.h OrthancServer/DatabaseWrapper.h OrthancServer/DatabaseWrapperBase.cpp OrthancServer/DatabaseWrapperBase.h OrthancServer/IDatabaseWrapper.h OrthancServer/LookupIdentifierQuery.cpp OrthancServer/LookupIdentifierQuery.h OrthancServer/ServerEnumerations.h OrthancServer/ServerIndex.cpp OrthancServer/SetOfResources.cpp OrthancServer/SetOfResources.h OrthancServer/main.cpp Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h Plugins/Include/orthanc/OrthancCDatabasePlugin.h Plugins/Include/orthanc/OrthancCPlugin.h Resources/ErrorCodes.json UnitTestsSources/ServerIndexTests.cpp |
diffstat | 20 files changed, 402 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Mon Oct 26 13:47:50 2015 +0100 +++ b/CMakeLists.txt Mon Oct 26 16:04:58 2015 +0100 @@ -185,6 +185,7 @@ OrthancServer/ServerEnumerations.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerToolbox.cpp + OrthancServer/SetOfResources.cpp OrthancServer/SliceOrdering.cpp OrthancServer/ToDcmtkBridge.cpp
--- a/Core/Enumerations.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/Core/Enumerations.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -148,6 +148,9 @@ case ErrorCode_StorageAreaPlugin: return "Error in the plugin implementing a custom storage area"; + case ErrorCode_EmptyRequest: + return "The request is empty"; + case ErrorCode_SQLiteNotOpened: return "SQLite: The database is not opened";
--- a/Core/Enumerations.h Mon Oct 26 13:47:50 2015 +0100 +++ b/Core/Enumerations.h Mon Oct 26 16:04:58 2015 +0100 @@ -79,6 +79,7 @@ ErrorCode_BadFont = 30 /*!< Badly formatted font file */, ErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, ErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, + ErrorCode_EmptyRequest = 33 /*!< The request is empty */, ErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, ErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, ErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */,
--- a/OrthancServer/DatabaseWrapper.h Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/DatabaseWrapper.h Mon Oct 26 16:04:58 2015 +0100 @@ -315,17 +315,13 @@ return base_.IsExistingResource(internalId); } - virtual void LookupIdentifierExact(std::list<int64_t>& target, - ResourceType level, - const DicomTag& tag, - const std::string& value) + virtual void LookupIdentifier(std::list<int64_t>& result, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value) { - base_.LookupIdentifierExact(target, level, tag, value); - } - - virtual void LookupIdentifier(const LookupIdentifierQuery& query) - { - base_.LookupIdentifier(query); + base_.LookupIdentifier(result, level, tag, type, value); } virtual void GetAllMetadata(std::map<MetadataType, std::string>& target,
--- a/OrthancServer/DatabaseWrapperBase.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/DatabaseWrapperBase.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -34,6 +34,7 @@ #include "DatabaseWrapperBase.h" #include <stdio.h> +#include <memory> namespace Orthanc { @@ -665,6 +666,11 @@ } + + /** + + TODO REMOVE THIS + void DatabaseWrapperBase::LookupIdentifierExact(std::list<int64_t>& target, ResourceType level, const DicomTag& tag, @@ -692,12 +698,56 @@ target.push_back(s.ColumnInt64(0)); } } + */ - void DatabaseWrapperBase::LookupIdentifier(const LookupIdentifierQuery& query) + void DatabaseWrapperBase::LookupIdentifier(std::list<int64_t>& target, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value) { - // TODO - throw OrthancException(ErrorCode_NotImplemented); + static const char* COMMON = ("SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " + "d.id = r.internalId AND r.resourceType=? AND " + "d.tagGroup=? AND d.tagElement=? AND "); + + std::auto_ptr<SQLite::Statement> s; + + switch (type) + { + case IdentifierConstraintType_Equal: + s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value=?")); + break; + + case IdentifierConstraintType_GreaterOrEqual: + s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value>=?")); + break; + + case IdentifierConstraintType_SmallerOrEqual: + s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value<=?")); + break; + + case IdentifierConstraintType_Wildcard: + s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value LIKE ?")); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + assert(s.get() != NULL); + + s->BindInt(0, level); + s->BindInt(1, tag.GetGroup()); + s->BindInt(2, tag.GetElement()); + s->BindString(3, value); + + target.clear(); + + while (s->Step()) + { + target.push_back(s->ColumnInt64(0)); + } } }
--- a/OrthancServer/DatabaseWrapperBase.h Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/DatabaseWrapperBase.h Mon Oct 26 16:04:58 2015 +0100 @@ -191,12 +191,11 @@ bool IsExistingResource(int64_t internalId); - void LookupIdentifierExact(std::list<int64_t>& target, - ResourceType level, - const DicomTag& tag, - const std::string& value); - - void LookupIdentifier(const LookupIdentifierQuery& query); + void LookupIdentifier(std::list<int64_t>& result, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value); }; }
--- a/OrthancServer/IDatabaseWrapper.h Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/IDatabaseWrapper.h Mon Oct 26 16:04:58 2015 +0100 @@ -44,8 +44,6 @@ namespace Orthanc { - class LookupIdentifierQuery; - class IDatabaseWrapper : public boost::noncopyable { public: @@ -148,12 +146,11 @@ virtual bool LookupGlobalProperty(std::string& target, GlobalProperty property) = 0; - virtual void LookupIdentifierExact(std::list<int64_t>& target, - ResourceType level, - const DicomTag& tag, - const std::string& value) = 0; - - virtual void LookupIdentifier(const LookupIdentifierQuery& query) = 0; + virtual void LookupIdentifier(std::list<int64_t>& result, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value) = 0; virtual bool LookupMetadata(std::string& target, int64_t id,
--- a/OrthancServer/LookupIdentifierQuery.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/LookupIdentifierQuery.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -34,7 +34,7 @@ #include "LookupIdentifierQuery.h" #include "../Core/OrthancException.h" - +#include "SetOfResources.h" #include <cassert> @@ -70,27 +70,6 @@ DICOM_TAG_SOP_INSTANCE_UID }; - - LookupIdentifierQuery::~LookupIdentifierQuery() - { - for (Constraints::iterator it = constraints_.begin(); - it != constraints_.end(); ++it) - { - delete *it; - } - } - - - - void LookupIdentifierQuery::CheckIndex(size_t index) const - { - if (index >= constraints_.size()) - { - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - } - - static void LoadIdentifiers(const DicomTag*& tags, size_t& size, ResourceType level) @@ -123,6 +102,27 @@ } + + LookupIdentifierQuery::~LookupIdentifierQuery() + { + for (Constraints::iterator it = constraints_.begin(); + it != constraints_.end(); ++it) + { + delete *it; + } + } + + + + void LookupIdentifierQuery::CheckIndex(size_t index) const + { + if (index >= constraints_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + bool LookupIdentifierQuery::IsIdentifier(const DicomTag& tag) const { const DicomTag* tags; @@ -202,4 +202,20 @@ } } } + + + void LookupIdentifierQuery::Apply(std::list<std::string>& result, + IDatabaseWrapper& database) + { + SetOfResources resources(database, level_); + + for (size_t i = 0; i < GetSize(); i++) + { + std::list<int64_t> tmp; + database.LookupIdentifier(tmp, level_, GetTag(i), GetType(i), GetValue(i)); + resources.Intersect(tmp); + } + + resources.Flatten(result); + } }
--- a/OrthancServer/LookupIdentifierQuery.h Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/LookupIdentifierQuery.h Mon Oct 26 16:04:58 2015 +0100 @@ -54,14 +54,12 @@ * corresponds to "%" (resp. "_") in primitive LIKE of SQL. The * values "%", "_", "\" should in the user request should * respectively be escaped as "\%", "\_" and "\\". - * + * * This matching must be case sensitive: The special case of PN VR * is taken into consideration by normalizing the query string in * method "NormalizeIdentifier()". **/ - - class LookupIdentifierQuery : public boost::noncopyable { private: @@ -103,7 +101,12 @@ IdentifierConstraintType type, const std::string& value); - size_t GetSize() + ResourceType GetLevel() const + { + return level_; + } + + size_t GetSize() const { return constraints_.size(); } @@ -118,6 +121,9 @@ int64_t resource, ResourceType level, const DicomMap& map); - + + // The database must be locked + void Apply(std::list<std::string>& result, + IDatabaseWrapper& database); }; }
--- a/OrthancServer/ServerEnumerations.h Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/ServerEnumerations.h Mon Oct 26 16:04:58 2015 +0100 @@ -128,9 +128,9 @@ enum IdentifierConstraintType { IdentifierConstraintType_Equal, - IdentifierConstraintType_LessOrEqual, - IdentifierConstraintType_GeaterOrEqual, - IdentifierConstraintType_Wildcard /* "*" or "?" are the only allowed wildcards */ + IdentifierConstraintType_SmallerOrEqual, + IdentifierConstraintType_GreaterOrEqual, + IdentifierConstraintType_Wildcard /* Case sensitive, "*" or "?" are the only allowed wildcards */ };
--- a/OrthancServer/ServerIndex.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/ServerIndex.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -45,6 +45,7 @@ #include "../Core/Logging.h" #include "../Core/Uuid.h" #include "../Core/DicomFormat/DicomArray.h" +#include "LookupIdentifierQuery.h" #include "FromDcmtkBridge.h" #include "ServerContext.h" @@ -1910,14 +1911,9 @@ boost::mutex::scoped_lock lock(mutex_); - std::list<int64_t> id; - db_.LookupIdentifierExact(id, level, tag, value); - - for (std::list<int64_t>::const_iterator - it = id.begin(); it != id.end(); ++it) - { - result.push_back(db_.GetPublicId(*it)); - } + LookupIdentifierQuery query(level); + query.AddConstraint(tag, IdentifierConstraintType_Equal, value); + query.Apply(result, db_); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/SetOfResources.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -0,0 +1,115 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, 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. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PrecompiledHeadersServer.h" +#include "SetOfResources.h" + +#include "../Core/OrthancException.h" + + +namespace Orthanc +{ + void SetOfResources::Intersect(const std::list<int64_t>& resources) + { + if (resources_.get() == NULL) + { + resources_.reset(new Resources); + + for (std::list<int64_t>::const_iterator + it = resources.begin(); it != resources.end(); ++it) + { + resources_->insert(*it); + } + } + else + { + std::auto_ptr<Resources> filtered(new Resources); + + for (std::list<int64_t>::const_iterator + it = resources.begin(); it != resources.end(); ++it) + { + if (resources_->find(*it) != resources_->end()) + { + filtered->insert(*it); + } + } + + resources_ = filtered; + } + } + + + void SetOfResources::GoDown() + { + if (level_ == ResourceType_Instance) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + std::auto_ptr<Resources> children(new Resources); + + for (Resources::const_iterator it = resources_->begin(); + it != resources_->end(); ++it) + { + std::list<int64_t> tmp; + database_.GetChildrenInternalId(tmp, *it); + + for (std::list<int64_t>::const_iterator + child = tmp.begin(); child != tmp.end(); ++child) + { + children->insert(*child); + } + } + + resources_ = children; + } + + + void SetOfResources::Flatten(std::list<std::string>& result) + { + result.clear(); + + if (resources_.get() == NULL) + { + // All the resources of this level are part of the filter + database_.GetAllPublicIds(result, level_); + } + else + { + for (Resources::const_iterator it = resources_->begin(); + it != resources_->end(); ++it) + { + result.push_back(database_.GetPublicId(*it)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/SetOfResources.h Mon Oct 26 16:04:58 2015 +0100 @@ -0,0 +1,71 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, 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. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IDatabaseWrapper.h" + +#include <set> +#include <boost/noncopyable.hpp> +#include <memory> + +namespace Orthanc +{ + class SetOfResources : public boost::noncopyable + { + private: + typedef std::set<int64_t> Resources; + + IDatabaseWrapper& database_; + ResourceType level_; + std::auto_ptr<Resources> resources_; + + public: + SetOfResources(IDatabaseWrapper& database, + ResourceType level) : + database_(database), + level_(level) + { + } + + ResourceType GetLevel() const + { + return level_; + } + + void Intersect(const std::list<int64_t>& resources); + + void GoDown(); + + void Flatten(std::list<std::string>& result); + }; +}
--- a/OrthancServer/main.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/OrthancServer/main.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -491,6 +491,7 @@ PrintErrorCode(ErrorCode_BadFont, "Badly formatted font file"); PrintErrorCode(ErrorCode_DatabasePlugin, "The plugin implementing a custom database back-end does not fulfill the proper interface"); PrintErrorCode(ErrorCode_StorageAreaPlugin, "Error in the plugin implementing a custom storage area"); + PrintErrorCode(ErrorCode_EmptyRequest, "The request is empty"); PrintErrorCode(ErrorCode_SQLiteNotOpened, "SQLite: The database is not opened"); PrintErrorCode(ErrorCode_SQLiteAlreadyOpened, "SQLite: Connection is already open"); PrintErrorCode(ErrorCode_SQLiteCannotOpen, "SQLite: Unable to open the database");
--- a/Plugins/Engine/OrthancPluginDatabase.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -594,6 +594,10 @@ } + /* + + TODO REMOVE THIS + void OrthancPluginDatabase::LookupIdentifierExact(std::list<int64_t>& target, ResourceType level, const DicomTag& tag, @@ -643,10 +647,14 @@ } } } - } + }*/ - void OrthancPluginDatabase::LookupIdentifier(const LookupIdentifierQuery& query) + void OrthancPluginDatabase::LookupIdentifier(std::list<int64_t>& result, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value) { // TODO throw OrthancException(ErrorCode_NotImplemented);
--- a/Plugins/Engine/OrthancPluginDatabase.h Mon Oct 26 13:47:50 2015 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.h Mon Oct 26 16:04:58 2015 +0100 @@ -203,12 +203,11 @@ virtual bool LookupGlobalProperty(std::string& target, GlobalProperty property); - virtual void LookupIdentifierExact(std::list<int64_t>& target, - ResourceType level, - const DicomTag& tag, - const std::string& value); - - virtual void LookupIdentifier(const LookupIdentifierQuery& query); + virtual void LookupIdentifier(std::list<int64_t>& result, + ResourceType level, + const DicomTag& tag, + IdentifierConstraintType type, + const std::string& value); virtual bool LookupMetadata(std::string& target, int64_t id,
--- a/Plugins/Include/orthanc/OrthancCDatabasePlugin.h Mon Oct 26 13:47:50 2015 +0100 +++ b/Plugins/Include/orthanc/OrthancCDatabasePlugin.h Mon Oct 26 16:04:58 2015 +0100 @@ -522,7 +522,7 @@ void* payload, int32_t property); - /* Use "OrthancPluginDatabaseExtensions::lookupIdentifierExact" + /* Use "OrthancPluginDatabaseExtensions::lookupIdentifier2" instead of this function as of Orthanc 0.9.5 (db v6), can be set to NULL. Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*lookupIdentifier) ( @@ -664,14 +664,17 @@ void* payload, int64_t id); +#if 0 /* Output: Use OrthancPluginDatabaseAnswerInt64() */ - OrthancPluginErrorCode (*lookupIdentifierExact) ( + OrthancPluginErrorCode (*lookupIdentifier2) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, OrthancPluginResourceType resourceType, const OrthancPluginDicomTag* tag); +#endif + } OrthancPluginDatabaseExtensions; /*<! @endcond */
--- a/Plugins/Include/orthanc/OrthancCPlugin.h Mon Oct 26 13:47:50 2015 +0100 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Mon Oct 26 16:04:58 2015 +0100 @@ -212,6 +212,7 @@ OrthancPluginErrorCode_BadFont = 30 /*!< Badly formatted font file */, OrthancPluginErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, OrthancPluginErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, + OrthancPluginErrorCode_EmptyRequest = 33 /*!< The request is empty */, OrthancPluginErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, OrthancPluginErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */,
--- a/Resources/ErrorCodes.json Mon Oct 26 13:47:50 2015 +0100 +++ b/Resources/ErrorCodes.json Mon Oct 26 16:04:58 2015 +0100 @@ -185,6 +185,11 @@ "Name": "StorageAreaPlugin", "Description": "Error in the plugin implementing a custom storage area" }, + { + "Code": 33, + "Name": "EmptyRequest", + "Description": "The request is empty" + },
--- a/UnitTestsSources/ServerIndexTests.cpp Mon Oct 26 13:47:50 2015 +0100 +++ b/UnitTestsSources/ServerIndexTests.cpp Mon Oct 26 16:04:58 2015 +0100 @@ -245,6 +245,18 @@ throw OrthancException(ErrorCode_InternalError); } } + + + void DoLookup(std::list<std::string>& result, + ResourceType level, + const DicomTag& tag, + const std::string& value) + { + LookupIdentifierQuery query(level); + query.AddConstraint(tag, IdentifierConstraintType_Equal, value); + query.Apply(result, *index_); + } + }; } @@ -690,36 +702,64 @@ index_->SetIdentifierTag(a[2], DICOM_TAG_STUDY_INSTANCE_UID, "0"); index_->SetIdentifierTag(a[3], DICOM_TAG_SERIES_INSTANCE_UID, "0"); - std::list<int64_t> s; + std::list<std::string> s; - index_->LookupIdentifierExact(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "0"); + DoLookup(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "0"); ASSERT_EQ(2u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), "a") != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), "c") != s.end()); - index_->LookupIdentifierExact(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, "0"); + DoLookup(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, "0"); ASSERT_EQ(1u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[3]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), "d") != s.end()); - index_->LookupIdentifierExact(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "1"); + DoLookup(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "1"); ASSERT_EQ(1u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), "b") != s.end()); - index_->LookupIdentifierExact(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "1"); + DoLookup(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, "1"); ASSERT_EQ(1u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), "b") != s.end()); - index_->LookupIdentifierExact(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, "1"); + DoLookup(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, "1"); ASSERT_EQ(0u, s.size()); - /*{ - std::list<std::string> s; - context.GetIndex().LookupIdentifierExact(s, DICOM_TAG_STUDY_INSTANCE_UID, "1.2.250.1.74.20130819132500.29000036381059"); - for (std::list<std::string>::iterator i = s.begin(); i != s.end(); i++) - { - std::cout << "*** " << *i << std::endl;; - } - }*/ + { + LookupIdentifierQuery query(ResourceType_Study); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_GreaterOrEqual, "0"); + query.Apply(s, *index_); + ASSERT_EQ(3u, s.size()); + } + + { + LookupIdentifierQuery query(ResourceType_Study); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_GreaterOrEqual, "0"); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_SmallerOrEqual, "0"); + query.Apply(s, *index_); + ASSERT_EQ(2u, s.size()); + } + + { + LookupIdentifierQuery query(ResourceType_Study); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_GreaterOrEqual, "1"); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_SmallerOrEqual, "1"); + query.Apply(s, *index_); + ASSERT_EQ(1u, s.size()); + } + + { + LookupIdentifierQuery query(ResourceType_Study); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_GreaterOrEqual, "1"); + query.Apply(s, *index_); + ASSERT_EQ(1u, s.size()); + } + + { + LookupIdentifierQuery query(ResourceType_Study); + query.AddConstraint(DICOM_TAG_STUDY_INSTANCE_UID, IdentifierConstraintType_GreaterOrEqual, "2"); + query.Apply(s, *index_); + ASSERT_EQ(0u, s.size()); + } }