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,