Mercurial > hg > orthanc
diff OrthancServer/ServerIndex.cpp @ 3027:fd587cf51a89 db-changes
cont
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 18 Dec 2018 12:50:27 +0100 |
parents | 039a9d262d64 |
children | ea653ec47f31 |
line wrap: on
line diff
--- a/OrthancServer/ServerIndex.cpp Mon Dec 17 17:05:28 2018 +0100 +++ b/OrthancServer/ServerIndex.cpp Tue Dec 18 12:50:27 2018 +0100 @@ -299,6 +299,107 @@ }; + class ServerIndex::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<DicomTag, TagInfo> 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)); + } + } + + DicomMap::LoadMainDicomTags(tags, size, level); + + for (size_t i = 0; i < size; i++) + { + if (registry_.find(tags[i]) == registry_.end()) + { + registry_[tags[i]] = 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(); + } + } + }; + + bool ServerIndex::DeleteResource(Json::Value& target, const std::string& uuid, ResourceType expectedType) @@ -541,7 +642,8 @@ db_(db), maximumStorageSize_(0), maximumPatients_(0), - overwrite_(false) + overwrite_(false), + mainDicomTagsRegistry_(new MainDicomTagsRegistry) { listener_.reset(new Listener(context)); db_.SetListener(*listener_); @@ -2454,15 +2556,92 @@ } + void ServerIndex::NormalizeLookup(DatabaseLookup& target, + const DatabaseLookup& source, + ResourceType queryLevel) const + { + assert(mainDicomTagsRegistry_.get() != NULL); + + for (size_t i = 0; i < source.GetConstraintsCount(); i++) + { + const DicomTagConstraint& constraint = source.GetConstraint(i); + + ResourceType tagLevel; + DicomTagType tagType; + mainDicomTagsRegistry_->LookupTag(tagLevel, tagType, constraint.GetTag()); + + if (IsResourceLevelAboveOrEqual(tagLevel, queryLevel) && + (tagType == DicomTagType_Identifier || + tagType == DicomTagType_Main)) + { + if (tagType == DicomTagType_Identifier) + { + if (constraint.GetConstraintType() == ConstraintType_List) + { + if (!constraint.GetValues().empty()) + { + std::auto_ptr<DicomTagConstraint> normalized( + new DicomTagConstraint(constraint.GetTag(), + ConstraintType_List, true, + constraint.IsMandatory())); + + normalized->SetTagType(tagType); + + for (std::set<std::string>::const_iterator + value = constraint.GetValues().begin(); + value != constraint.GetValues().end(); ++value) + { + normalized->AddValue(ServerToolbox::NormalizeIdentifier(*value)); + } + + target.AddConstraint(normalized.release()); + } + } + else + { + std::string value = ServerToolbox::NormalizeIdentifier(constraint.GetValue()); + + std::auto_ptr<DicomTagConstraint> normalized( + new DicomTagConstraint(constraint.GetTag(), + constraint.GetConstraintType(), + value, true, + constraint.IsMandatory())); + + normalized->SetTagType(tagType); + target.AddConstraint(normalized.release()); + } + } + else if (tagType == DicomTagType_Main) + { + std::auto_ptr<DicomTagConstraint> clone(constraint.Clone()); + clone->SetTagType(tagType); + target.AddConstraint(clone.release()); + } + else if (tagType == DicomTagType_Generic) + { + // This tag is not indexed in the database, skip it + } + else + { + throw OrthancException(ErrorCode_InternalError); + } + } + } + } + + void ServerIndex::ApplyLookupPatients(std::vector<std::string>& patientsId, std::vector<std::string>& instancesId, const DatabaseLookup& lookup, size_t limit) { - boost::mutex::scoped_lock lock(mutex_); - - db_.ApplyLookupPatients(patientsId, lookup, limit); - db_.FindOneChildInstance(instancesId, patientsId, ResourceType_Patient); + DatabaseLookup normalized; + NormalizeLookup(normalized, lookup, ResourceType_Patient); + + { + boost::mutex::scoped_lock lock(mutex_); + db_.ApplyLookupPatients(patientsId, instancesId, normalized, limit); + } } @@ -2472,9 +2651,12 @@ ResourceType queryLevel, size_t limit) { - boost::mutex::scoped_lock lock(mutex_); - - db_.ApplyLookupResources(resourcesId, lookup, queryLevel, limit); - db_.FindOneChildInstance(instancesId, resourcesId, queryLevel); + DatabaseLookup normalized; + NormalizeLookup(normalized, lookup, queryLevel); + + { + boost::mutex::scoped_lock lock(mutex_); + db_.ApplyLookupResources(resourcesId, instancesId, normalized, queryLevel, limit); + } } }