Mercurial > hg > orthanc
diff OrthancServer/Search/Compatibility/DatabaseLookup.cpp @ 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 | 5ebd2ef5e7ae |
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); + } }