ReusableDicomUserConnection::Locker::Locker(ReusableDicomUserConnection& that, const RemoteModalityParameters& remote) : ::Orthanc::Locker(that) { that.Open(remote.GetApplicationEntityTitle(), remote.GetHost(), remote.GetPort(), remote.GetManufacturer()); connection_ = that.connection_; }
void ReusableDicomUserConnection::Open(const std::string& localAet, const RemoteModalityParameters& remote) { if (connection_ != NULL && connection_->GetLocalApplicationEntityTitle() == localAet && connection_->GetRemoteApplicationEntityTitle() == remote.GetApplicationEntityTitle() && connection_->GetRemoteHost() == remote.GetHost() && connection_->GetRemotePort() == remote.GetPort() && connection_->GetRemoteManufacturer() == remote.GetManufacturer()) { // The current connection can be reused LOG(INFO) << "Reusing the previous SCU connection"; return; } Close(); connection_ = new DicomUserConnection(); connection_->SetLocalApplicationEntityTitle(localAet); connection_->SetRemoteModality(remote); connection_->Open(); }
void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, const DicomMap& input, const std::list<DicomTag>& sequencesToReturn, const std::string& remoteIp, const std::string& remoteAet, const std::string& calledAet) { /** * Ensure that the remote modality is known to Orthanc. **/ RemoteModalityParameters modality; if (!Configuration::LookupDicomModalityUsingAETitle(modality, remoteAet)) { throw OrthancException(ErrorCode_UnknownModality); } bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false); /** * Possibly apply the user-supplied Lua filter. **/ DicomMap lua; const DicomMap* filteredInput = &input; if (ApplyLuaFilter(lua, input, remoteIp, remoteAet, calledAet)) { filteredInput = &lua; } /** * Retrieve the query level. **/ assert(filteredInput != NULL); const DicomValue* levelTmp = filteredInput->TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL); if (levelTmp == NULL || levelTmp->IsNull() || levelTmp->IsBinary()) { LOG(ERROR) << "C-FIND request without the tag 0008,0052 (QueryRetrieveLevel)"; throw OrthancException(ErrorCode_BadRequest); } ResourceType level = StringToResourceType(levelTmp->GetContent().c_str()); if (level != ResourceType_Patient && level != ResourceType_Study && level != ResourceType_Series && level != ResourceType_Instance) { throw OrthancException(ErrorCode_NotImplemented); } DicomArray query(*filteredInput); LOG(INFO) << "DICOM C-Find request at level: " << EnumerationToString(level); for (size_t i = 0; i < query.GetSize(); i++) { if (!query.GetElement(i).GetValue().IsNull()) { LOG(INFO) << " " << query.GetElement(i).GetTag() << " " << FromDcmtkBridge::GetName(query.GetElement(i).GetTag()) << " = " << query.GetElement(i).GetValue().GetContent(); } } for (std::list<DicomTag>::const_iterator it = sequencesToReturn.begin(); it != sequencesToReturn.end(); ++it) { LOG(INFO) << " (" << it->Format() << ") " << FromDcmtkBridge::GetName(*it) << " : sequence tag whose content will be copied"; } /** * Build up the query object. **/ LookupResource finder(level); for (size_t i = 0; i < query.GetSize(); i++) { const DicomTag tag = query.GetElement(i).GetTag(); if (query.GetElement(i).GetValue().IsNull() || tag == DICOM_TAG_QUERY_RETRIEVE_LEVEL || tag == DICOM_TAG_SPECIFIC_CHARACTER_SET) { continue; } std::string value = query.GetElement(i).GetValue().GetContent(); if (value.size() == 0) { // An empty string corresponds to a "*" wildcard constraint, so we ignore it continue; } if (FilterQueryTag(value, level, tag, modality.GetManufacturer())) { ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(tag); // DICOM specifies that searches must be case sensitive, except // for tags with a PN value representation bool sensitive = true; if (vr == ValueRepresentation_PersonName) { sensitive = caseSensitivePN; } finder.AddDicomConstraint(tag, value, sensitive); } else { LOG(INFO) << "Because of a patch for the manufacturer of the remote modality, " << "ignoring constraint on tag (" << tag.Format() << ") " << FromDcmtkBridge::GetName(tag); } } /** * Run the query. **/ size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; std::vector<std::string> resources, instances; context_.GetIndex().FindCandidates(resources, instances, finder); assert(resources.size() == instances.size()); bool complete = true; for (size_t i = 0; i < instances.size(); i++) { Json::Value dicom; context_.ReadJson(dicom, instances[i]); if (finder.IsMatch(dicom)) { if (maxResults != 0 && answers.GetSize() >= maxResults) { complete = false; break; } else { std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instances[i], level, input)); AddAnswer(answers, dicom, query, sequencesToReturn, counters.get()); } } } LOG(INFO) << "Number of matching resources: " << answers.GetSize(); answers.SetComplete(complete); }