Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancFindRequestHandler.cpp @ 5696:0f8b6214308a find-refactoring
preparing to use ResourceFinder in OrthancFindRequestHandler
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Jul 2024 10:56:33 +0200 |
parents | f7adfb22e20e |
children | 075558c95cbb |
comparison
equal
deleted
inserted
replaced
5695:380a71e0d7e7 | 5696:0f8b6214308a |
---|---|
28 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" | 28 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" |
29 #include "../../OrthancFramework/Sources/Logging.h" | 29 #include "../../OrthancFramework/Sources/Logging.h" |
30 #include "../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" | 30 #include "../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" |
31 #include "../../OrthancFramework/Sources/MetricsRegistry.h" | 31 #include "../../OrthancFramework/Sources/MetricsRegistry.h" |
32 #include "OrthancConfiguration.h" | 32 #include "OrthancConfiguration.h" |
33 #include "ResourceFinder.cpp" | |
33 #include "Search/DatabaseLookup.h" | 34 #include "Search/DatabaseLookup.h" |
34 #include "ServerContext.h" | 35 #include "ServerContext.h" |
35 #include "ServerToolbox.h" | 36 #include "ServerToolbox.h" |
36 | 37 |
37 #include <boost/regex.hpp> | 38 #include <boost/regex.hpp> |
317 defaultPrivateCreator_, privateCreators_, retrieveAet_, IsStorageAccessAllowedForAnswers(findStorageAccessMode_)); | 318 defaultPrivateCreator_, privateCreators_, retrieveAet_, IsStorageAccessAllowedForAnswers(findStorageAccessMode_)); |
318 } | 319 } |
319 }; | 320 }; |
320 | 321 |
321 | 322 |
323 namespace | |
324 { | |
325 class LookupVisitorV2 : public ResourceFinder::IVisitor | |
326 { | |
327 private: | |
328 DicomFindAnswers& answers_; | |
329 ServerContext& context_; | |
330 ResourceType level_; | |
331 const DicomMap& query_; | |
332 DicomArray queryAsArray_; | |
333 const std::list<DicomTag>& sequencesToReturn_; | |
334 std::string defaultPrivateCreator_; // the private creator to use if the group is not defined in the query itself | |
335 const std::map<uint16_t, std::string>& privateCreators_; // the private creators defined in the query itself | |
336 std::string retrieveAet_; | |
337 FindStorageAccessMode findStorageAccessMode_; | |
338 | |
339 public: | |
340 LookupVisitorV2(DicomFindAnswers& answers, | |
341 ServerContext& context, | |
342 ResourceType level, | |
343 const DicomMap& query, | |
344 const std::list<DicomTag>& sequencesToReturn, | |
345 const std::map<uint16_t, std::string>& privateCreators, | |
346 FindStorageAccessMode findStorageAccessMode) : | |
347 answers_(answers), | |
348 context_(context), | |
349 level_(level), | |
350 query_(query), | |
351 queryAsArray_(query), | |
352 sequencesToReturn_(sequencesToReturn), | |
353 privateCreators_(privateCreators), | |
354 findStorageAccessMode_(findStorageAccessMode) | |
355 { | |
356 answers_.SetComplete(false); | |
357 | |
358 { | |
359 OrthancConfiguration::ReaderLock lock; | |
360 defaultPrivateCreator_ = lock.GetConfiguration().GetDefaultPrivateCreator(); | |
361 retrieveAet_ = lock.GetConfiguration().GetOrthancAET(); | |
362 } | |
363 } | |
364 | |
365 virtual void Apply(const FindResponse::Resource& resource, | |
366 const DicomMap& requestedTags) ORTHANC_OVERRIDE | |
367 { | |
368 DicomMap answer; | |
369 resource.GetAllMainDicomTags(answer); | |
370 answer.Merge(requestedTags); | |
371 | |
372 /** | |
373 * Add the mandatory "Retrieve AE Title (0008,0054)" tag, which was missing in Orthanc <= 1.7.2. | |
374 * http://dicom.nema.org/medical/dicom/current/output/html/part04.html#sect_C.4.1.1.3.2 | |
375 * https://groups.google.com/g/orthanc-users/c/-7zNTKR_PMU/m/kfjwzEVNAgAJ | |
376 **/ | |
377 answer.SetValue(DICOM_TAG_RETRIEVE_AE_TITLE, retrieveAet_, false /* not binary */); | |
378 | |
379 for (size_t i = 0; i < queryAsArray_.GetSize(); i++) | |
380 { | |
381 const DicomTag tag = queryAsArray_.GetElement(i).GetTag(); | |
382 | |
383 if (tag == DICOM_TAG_QUERY_RETRIEVE_LEVEL) | |
384 { | |
385 // Fix issue 30 on Google Code (QR response missing "Query/Retrieve Level" (008,0052)) | |
386 answer.SetValue(tag, queryAsArray_.GetElement(i).GetValue()); | |
387 } | |
388 else if (tag == DICOM_TAG_SPECIFIC_CHARACTER_SET) | |
389 { | |
390 // Do not include the encoding, this is handled by class ParsedDicomFile | |
391 } | |
392 else if (!answer.HasTag(tag)) | |
393 { | |
394 answer.SetValue(tag, "", false); | |
395 } | |
396 } | |
397 | |
398 answers_.Add(answer); | |
399 } | |
400 | |
401 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
402 { | |
403 answers_.SetComplete(true); | |
404 } | |
405 }; | |
406 } | |
407 | |
408 | |
322 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, | 409 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, |
323 const DicomMap& input, | 410 const DicomMap& input, |
324 const std::list<DicomTag>& sequencesToReturn, | 411 const std::list<DicomTag>& sequencesToReturn, |
325 const std::string& remoteIp, | 412 const std::string& remoteIp, |
326 const std::string& remoteAet, | 413 const std::string& remoteAet, |
408 << ") " << FromDcmtkBridge::GetTagName(query.GetElement(i)) | 495 << ") " << FromDcmtkBridge::GetTagName(query.GetElement(i)) |
409 << " = " << context_.GetDeidentifiedContent(query.GetElement(i)); | 496 << " = " << context_.GetDeidentifiedContent(query.GetElement(i)); |
410 } | 497 } |
411 } | 498 } |
412 | 499 |
500 std::set<DicomTag> requestedTags; | |
501 | |
413 for (std::list<DicomTag>::const_iterator it = sequencesToReturn.begin(); | 502 for (std::list<DicomTag>::const_iterator it = sequencesToReturn.begin(); |
414 it != sequencesToReturn.end(); ++it) | 503 it != sequencesToReturn.end(); ++it) |
415 { | 504 { |
505 requestedTags.insert(*it); | |
416 CLOG(INFO, DICOM) << " (" << it->Format() | 506 CLOG(INFO, DICOM) << " (" << it->Format() |
417 << ") " << FromDcmtkBridge::GetTagName(*it, "") | 507 << ") " << FromDcmtkBridge::GetTagName(*it, "") |
418 << " : sequence tag whose content will be copied"; | 508 << " : sequence tag whose content will be copied"; |
419 } | 509 } |
420 | 510 |
451 | 541 |
452 std::string value = element.GetValue().GetContent(); | 542 std::string value = element.GetValue().GetContent(); |
453 if (value.size() == 0) | 543 if (value.size() == 0) |
454 { | 544 { |
455 // An empty string corresponds to an universal constraint, so we ignore it | 545 // An empty string corresponds to an universal constraint, so we ignore it |
546 requestedTags.insert(tag); | |
456 continue; | 547 continue; |
457 } | 548 } |
458 | 549 |
459 if (FilterQueryTag(value, level, tag, manufacturer)) | 550 if (FilterQueryTag(value, level, tag, manufacturer)) |
460 { | 551 { |
470 | 561 |
471 lookup.AddDicomConstraint(tag, value, sensitive, true /* mandatory */); | 562 lookup.AddDicomConstraint(tag, value, sensitive, true /* mandatory */); |
472 } | 563 } |
473 else | 564 else |
474 { | 565 { |
566 requestedTags.insert(tag); | |
475 CLOG(INFO, DICOM) << "Because of a patch for the manufacturer of the remote modality, " | 567 CLOG(INFO, DICOM) << "Because of a patch for the manufacturer of the remote modality, " |
476 << "ignoring constraint on tag (" << tag.Format() << ") " | 568 << "ignoring constraint on tag (" << tag.Format() << ") " |
477 << FromDcmtkBridge::GetTagName(element); | 569 << FromDcmtkBridge::GetTagName(element); |
478 } | 570 } |
479 } | 571 } |
484 **/ | 576 **/ |
485 | 577 |
486 size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; | 578 size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; |
487 | 579 |
488 | 580 |
489 LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn, privateCreators, context_.GetFindStorageAccessMode()); | 581 if (false) |
490 context_.Apply(visitor, lookup, level, 0 /* "since" is not relevant to C-FIND */, limit); | 582 { |
583 /** | |
584 * EXPERIMENTAL VERSION | |
585 **/ | |
586 | |
587 ResourceFinder finder(level, false /* don't expand */); | |
588 finder.SetDatabaseLookup(lookup); | |
589 finder.AddRequestedTags(requestedTags); | |
590 | |
591 LookupVisitorV2 visitor(answers, context_, level, *filteredInput, sequencesToReturn, privateCreators, context_.GetFindStorageAccessMode()); | |
592 finder.Execute(visitor, context_); | |
593 } | |
594 else | |
595 { | |
596 /** | |
597 * VERSION IN ORTHANC <= 1.12.4 | |
598 **/ | |
599 | |
600 LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn, privateCreators, context_.GetFindStorageAccessMode()); | |
601 context_.Apply(visitor, lookup, level, 0 /* "since" is not relevant to C-FIND */, limit); | |
602 } | |
491 } | 603 } |
492 | 604 |
493 | 605 |
494 void OrthancFindRequestHandler::FormatOrigin(Json::Value& origin, | 606 void OrthancFindRequestHandler::FormatOrigin(Json::Value& origin, |
495 const std::string& remoteIp, | 607 const std::string& remoteIp, |