Mercurial > hg > orthanc
changeset 3055:71ac4f28176f db-changes
compatibility layer seems to be working
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 21 Dec 2018 13:36:30 +0100 |
parents | 3638de45a08c |
children | 6c5d4281da4a |
files | OrthancServer/Search/Compatibility/DatabaseLookup.cpp OrthancServer/Search/DatabaseConstraint.h OrthancServer/Search/DicomTagConstraint.cpp OrthancServer/Search/DicomTagConstraint.h |
diffstat | 4 files changed, 171 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/Search/Compatibility/DatabaseLookup.cpp Fri Dec 21 12:45:24 2018 +0100 +++ b/OrthancServer/Search/Compatibility/DatabaseLookup.cpp Fri Dec 21 13:36:30 2018 +0100 @@ -42,6 +42,55 @@ { namespace Compatibility { + namespace + { + // Anonymous namespace to avoid clashes between compiler modules + class MainTagsConstraints : boost::noncopyable + { + private: + std::vector<DicomTagConstraint*> constraints_; + + public: + ~MainTagsConstraints() + { + for (size_t i = 0; i < constraints_.size(); i++) + { + assert(constraints_[i] != NULL); + delete constraints_[i]; + } + } + + void Reserve(size_t n) + { + constraints_.reserve(n); + } + + size_t GetSize() const + { + return constraints_.size(); + } + + DicomTagConstraint& GetConstraint(size_t i) const + { + if (i >= constraints_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + assert(constraints_[i] != NULL); + return *constraints_[i]; + } + } + + void Add(const DatabaseConstraint& constraint) + { + constraints_.push_back(new DicomTagConstraint(constraint)); + } + }; + } + + static void ApplyIdentifierConstraint(SetOfResources& candidates, CompatibilityDatabaseWrapper& database, const DatabaseConstraint& constraint, @@ -74,7 +123,6 @@ break; case ConstraintType_List: - { for (size_t i = 0; i < constraint.GetValuesCount(); i++) { std::list<int64_t> tmp; @@ -84,7 +132,6 @@ } break; - } default: throw OrthancException(ErrorCode_InternalError); @@ -120,6 +167,10 @@ typedef std::set<const DatabaseConstraint*> SetOfConstraints; typedef std::map<DicomTag, SetOfConstraints> Identifiers; + // (1) Select which constraints apply to this level, and split + // them between "identifier tags" constraints and "main DICOM + // tags" constraints + Identifiers identifiers; SetOfConstraints mainTags; @@ -138,15 +189,22 @@ } } + + // (2) Apply the constraints over the identifiers + for (Identifiers::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it) { + // Check whether some range constraint over identifiers is + // present at this level const DatabaseConstraint* smaller = NULL; const DatabaseConstraint* greater = NULL; for (SetOfConstraints::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { + assert(*it2 != NULL); + if ((*it2)->GetConstraintType() == ConstraintType_SmallerOrEqual) { smaller = *it2; @@ -161,6 +219,7 @@ if (smaller != NULL && greater != NULL) { + // There is a range constraint: Apply it, as it is more efficient ApplyIdentifierRange(candidates, database, *smaller, *greater, level); } else @@ -172,6 +231,7 @@ for (SetOfConstraints::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { + // Check to avoid applying twice the range constraint if (*it2 != smaller && *it2 != greater) { @@ -181,7 +241,51 @@ } - // TODO - Fiter main DICOM tags + // (3) Apply the constraints over the main DICOM tags (no index + // here, so this is less efficient than filtering over the + // identifiers) + if (!mainTags.empty()) + { + MainTagsConstraints c; + c.Reserve(mainTags.size()); + + for (SetOfConstraints::const_iterator it = mainTags.begin(); + it != mainTags.end(); ++it) + { + assert(*it != NULL); + c.Add(**it); + } + + std::list<int64_t> source; + candidates.Flatten(source); + candidates.Clear(); + + std::list<int64_t> filtered; + for (std::list<int64_t>::const_iterator candidate = source.begin(); + candidate != source.end(); ++candidate) + { + DicomMap tags; + database.GetMainDicomTags(tags, *candidate); + + bool match = true; + + for (size_t i = 0; i < c.GetSize(); i++) + { + if (!c.GetConstraint(i).IsMatch(tags)) + { + match = false; + break; + } + } + + if (match) + { + filtered.push_back(*candidate); + } + } + + candidates.Intersect(filtered); + } }
--- a/OrthancServer/Search/DatabaseConstraint.h Fri Dec 21 12:45:24 2018 +0100 +++ b/OrthancServer/Search/DatabaseConstraint.h Fri Dec 21 13:36:30 2018 +0100 @@ -91,5 +91,7 @@ { return mandatory_; } + + bool IsMatch(const DicomMap& dicom) const; }; }
--- a/OrthancServer/Search/DicomTagConstraint.cpp Fri Dec 21 12:45:24 2018 +0100 +++ b/OrthancServer/Search/DicomTagConstraint.cpp Fri Dec 21 13:36:30 2018 +0100 @@ -36,6 +36,8 @@ #include "../../Core/OrthancException.h" #include "../../Core/Toolbox.h" +#include "../ServerToolbox.h" +#include "DatabaseConstraint.h" #include <boost/regex.hpp> @@ -94,6 +96,30 @@ }; + void DicomTagConstraint::AssignSingleValue(const std::string& value) + { + if (constraintType_ != ConstraintType_Wildcard && + (value.find('*') != std::string::npos || + value.find('?') != std::string::npos)) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + if (constraintType_ == ConstraintType_Equal || + constraintType_ == ConstraintType_SmallerOrEqual || + constraintType_ == ConstraintType_GreaterOrEqual || + constraintType_ == ConstraintType_Wildcard) + { + values_.clear(); + values_.insert(value); + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + DicomTagConstraint::DicomTagConstraint(const DicomTag& tag, ConstraintType type, const std::string& value, @@ -104,24 +130,7 @@ caseSensitive_(caseSensitive), mandatory_(mandatory) { - if (type == ConstraintType_Equal || - type == ConstraintType_SmallerOrEqual || - type == ConstraintType_GreaterOrEqual || - type == ConstraintType_Wildcard) - { - values_.insert(value); - } - else - { - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - - if (type != ConstraintType_Wildcard && - (value.find('*') != std::string::npos || - value.find('?') != std::string::npos)) - { - throw OrthancException(ErrorCode_ParameterOutOfRange); - } + AssignSingleValue(value); } @@ -141,6 +150,35 @@ } + DicomTagConstraint::DicomTagConstraint(const DatabaseConstraint& constraint) : + tag_(constraint.GetTag()), + constraintType_(constraint.GetConstraintType()), + caseSensitive_(constraint.IsCaseSensitive()), + mandatory_(constraint.IsMandatory()) + { + assert(constraint.IsIdentifier() == + ServerToolbox::IsIdentifier(constraint.GetTag(), constraint.GetLevel())); + + if (constraint.IsIdentifier()) + { + // This conversion is only available for main DICOM tags, not for identifers + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + if (constraintType_ == ConstraintType_List) + { + for (size_t i = 0; i < constraint.GetValuesCount(); i++) + { + AddValue(constraint.GetValue(i)); + } + } + else + { + AssignSingleValue(constraint.GetSingleValue()); + } + } + + void DicomTagConstraint::AddValue(const std::string& value) { if (constraintType_ != ConstraintType_List)
--- a/OrthancServer/Search/DicomTagConstraint.h Fri Dec 21 12:45:24 2018 +0100 +++ b/OrthancServer/Search/DicomTagConstraint.h Fri Dec 21 13:36:30 2018 +0100 @@ -40,6 +40,8 @@ namespace Orthanc { + class DatabaseConstraint; + class DicomTagConstraint : public boost::noncopyable { private: @@ -54,6 +56,8 @@ boost::shared_ptr<RegularExpression> regex_; + void AssignSingleValue(const std::string& value); + public: DicomTagConstraint(const DicomTag& tag, ConstraintType type, @@ -67,6 +71,8 @@ bool caseSensitive, bool mandatory); + DicomTagConstraint(const DatabaseConstraint& constraint); + const DicomTag& GetTag() const { return tag_;