Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerContext.cpp @ 5707:c8d21a09aae6 find-refactoring-clean
removed ServerContext::ILookupVisitor
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Jul 2024 17:58:15 +0200 |
parents | 708952bd869c |
children | 52771e1a8072 |
comparison
equal
deleted
inserted
replaced
5706:1404a80dd461 | 5707:c8d21a09aae6 |
---|---|
1529 return false; | 1529 return false; |
1530 #endif | 1530 #endif |
1531 } | 1531 } |
1532 | 1532 |
1533 | 1533 |
1534 void ServerContext::Apply(ILookupVisitor& visitor, | |
1535 const DatabaseLookup& lookup, | |
1536 ResourceType queryLevel, | |
1537 const std::set<std::string>& labels, | |
1538 LabelsConstraint labelsConstraint, | |
1539 size_t since, | |
1540 size_t limit) | |
1541 { | |
1542 const uint64_t databaseLimit = GetDatabaseLimits(queryLevel); | |
1543 | |
1544 std::vector<std::string> resources, instances; | |
1545 const DicomTagConstraint* dicomModalitiesConstraint = NULL; | |
1546 | |
1547 bool hasModalitiesInStudyLookup = (queryLevel == ResourceType_Study && | |
1548 lookup.GetConstraint(dicomModalitiesConstraint, DICOM_TAG_MODALITIES_IN_STUDY) && | |
1549 ((dicomModalitiesConstraint->GetConstraintType() == ConstraintType_Equal && !dicomModalitiesConstraint->GetValue().empty()) || | |
1550 (dicomModalitiesConstraint->GetConstraintType() == ConstraintType_List && !dicomModalitiesConstraint->GetValues().empty()))); | |
1551 | |
1552 std::unique_ptr<DatabaseLookup> fastLookup(lookup.Clone()); | |
1553 | |
1554 if (hasModalitiesInStudyLookup) | |
1555 { | |
1556 fastLookup->RemoveConstraint(DICOM_TAG_MODALITIES_IN_STUDY); | |
1557 } | |
1558 | |
1559 if (true) | |
1560 { | |
1561 /** | |
1562 * EXPERIMENTAL VERSION | |
1563 **/ | |
1564 | |
1565 ResourceFinder finder(queryLevel, false /* TODO-FIND: don't expand for now */); | |
1566 finder.SetDatabaseLimits(databaseLimit); | |
1567 finder.SetDatabaseLookup(lookup); | |
1568 finder.SetLabels(labels); | |
1569 finder.SetLabelsConstraint(labelsConstraint); | |
1570 | |
1571 if (queryLevel != ResourceType_Instance) | |
1572 { | |
1573 finder.SetRetrieveOneInstanceIdentifier(true); | |
1574 } | |
1575 | |
1576 FindResponse response; | |
1577 finder.Execute(response, GetIndex()); | |
1578 | |
1579 resources.resize(response.GetSize()); | |
1580 instances.resize(response.GetSize()); | |
1581 | |
1582 for (size_t i = 0; i < response.GetSize(); i++) | |
1583 { | |
1584 const FindResponse::Resource& resource = response.GetResourceByIndex(i); | |
1585 resources[i] = resource.GetIdentifier(); | |
1586 | |
1587 if (queryLevel == ResourceType_Instance) | |
1588 { | |
1589 instances[i] = resource.GetIdentifier(); | |
1590 } | |
1591 else | |
1592 { | |
1593 instances[i] = resource.GetOneInstanceIdentifier(); | |
1594 } | |
1595 } | |
1596 } | |
1597 else | |
1598 { | |
1599 /** | |
1600 * VERSION IN ORTHANC <= 1.12.4 | |
1601 **/ | |
1602 | |
1603 const size_t lookupLimit = (databaseLimit == 0 ? 0 : databaseLimit + 1); | |
1604 GetIndex().ApplyLookupResources(resources, &instances, *fastLookup, queryLevel, labels, labelsConstraint, lookupLimit); | |
1605 } | |
1606 | |
1607 bool complete = (databaseLimit == 0 || | |
1608 resources.size() <= databaseLimit); | |
1609 | |
1610 LOG(INFO) << "Number of candidate resources after fast DB filtering on main DICOM tags: " << resources.size(); | |
1611 | |
1612 /** | |
1613 * "resources" contains the Orthanc ID of the resource at level | |
1614 * "queryLevel", "instances" contains one the Orthanc ID of one | |
1615 * sample instance from this resource. | |
1616 **/ | |
1617 assert(resources.size() == instances.size()); | |
1618 | |
1619 size_t countResults = 0; | |
1620 size_t skipped = 0; | |
1621 | |
1622 const bool isDicomAsJsonNeeded = visitor.IsDicomAsJsonNeeded(); | |
1623 | |
1624 for (size_t i = 0; i < instances.size(); i++) | |
1625 { | |
1626 // Optimization in Orthanc 1.5.1 - Don't read the full JSON from | |
1627 // the disk if only "main DICOM tags" are to be returned | |
1628 | |
1629 boost::shared_ptr<Json::Value> dicomAsJson; | |
1630 | |
1631 bool hasOnlyMainDicomTags; | |
1632 DicomMap dicom; | |
1633 DicomMap allMainDicomTagsFromDB; | |
1634 | |
1635 if (!IsStorageAccessAllowedForAnswers(findStorageAccessMode_) | |
1636 || fastLookup->HasOnlyMainDicomTags()) | |
1637 { | |
1638 // Case (1): The main DICOM tags, as stored in the database, | |
1639 // are sufficient to look for match | |
1640 | |
1641 if (!GetIndex().GetAllMainDicomTags(allMainDicomTagsFromDB, instances[i])) | |
1642 { | |
1643 // The instance has been removed during the execution of the | |
1644 // lookup, ignore it | |
1645 continue; | |
1646 } | |
1647 | |
1648 // New in Orthanc 1.6.0: Only keep the main DICOM tags at the | |
1649 // level of interest for the query | |
1650 switch (queryLevel) | |
1651 { | |
1652 // WARNING: Don't reorder cases below, and don't add "break" | |
1653 case ResourceType_Instance: | |
1654 dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Instance); | |
1655 | |
1656 case ResourceType_Series: | |
1657 dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Series); | |
1658 | |
1659 case ResourceType_Study: | |
1660 dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Study); | |
1661 | |
1662 case ResourceType_Patient: | |
1663 dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Patient); | |
1664 break; | |
1665 | |
1666 default: | |
1667 throw OrthancException(ErrorCode_InternalError); | |
1668 } | |
1669 | |
1670 hasOnlyMainDicomTags = true; | |
1671 } | |
1672 else | |
1673 { | |
1674 // Case (2): Need to read the "DICOM-as-JSON" attachment from | |
1675 // the storage area | |
1676 dicomAsJson.reset(new Json::Value); | |
1677 ReadDicomAsJson(*dicomAsJson, instances[i]); | |
1678 | |
1679 dicom.FromDicomAsJson(*dicomAsJson); | |
1680 | |
1681 // This map contains the entire JSON, i.e. more than the main DICOM tags | |
1682 hasOnlyMainDicomTags = false; | |
1683 } | |
1684 | |
1685 if (fastLookup->IsMatch(dicom)) | |
1686 { | |
1687 bool isMatch = true; | |
1688 | |
1689 if (hasModalitiesInStudyLookup) | |
1690 { | |
1691 std::set<DicomTag> requestedTags; | |
1692 requestedTags.insert(DICOM_TAG_MODALITIES_IN_STUDY); | |
1693 ExpandedResource resource; | |
1694 ComputeStudyTags(resource, *this, resources[i], requestedTags); | |
1695 | |
1696 std::vector<std::string> modalities; | |
1697 Toolbox::TokenizeString(modalities, resource.GetMainDicomTags().GetValue(DICOM_TAG_MODALITIES_IN_STUDY).GetContent(), '\\'); | |
1698 bool hasAtLeastOneModalityMatching = false; | |
1699 for (size_t m = 0; m < modalities.size(); m++) | |
1700 { | |
1701 hasAtLeastOneModalityMatching |= dicomModalitiesConstraint->IsMatch(modalities[m]); | |
1702 } | |
1703 | |
1704 isMatch = isMatch && hasAtLeastOneModalityMatching; | |
1705 // copy the value of ModalitiesInStudy such that it can be reused to build the answer | |
1706 allMainDicomTagsFromDB.SetValue(DICOM_TAG_MODALITIES_IN_STUDY, resource.GetMainDicomTags().GetValue(DICOM_TAG_MODALITIES_IN_STUDY)); | |
1707 } | |
1708 | |
1709 if (isMatch) | |
1710 { | |
1711 if (skipped < since) | |
1712 { | |
1713 skipped++; | |
1714 } | |
1715 else if (limit != 0 && | |
1716 countResults >= limit) | |
1717 { | |
1718 // Too many results, don't mark as complete | |
1719 complete = false; | |
1720 break; | |
1721 } | |
1722 else | |
1723 { | |
1724 if (IsStorageAccessAllowedForAnswers(findStorageAccessMode_) && | |
1725 dicomAsJson.get() == NULL && | |
1726 isDicomAsJsonNeeded) | |
1727 { | |
1728 dicomAsJson.reset(new Json::Value); | |
1729 ReadDicomAsJson(*dicomAsJson, instances[i]); | |
1730 } | |
1731 | |
1732 if (hasOnlyMainDicomTags) | |
1733 { | |
1734 // This is Case (1): The variable "dicom" only contains the main DICOM tags | |
1735 visitor.Visit(resources[i], instances[i], allMainDicomTagsFromDB, dicomAsJson.get()); | |
1736 } | |
1737 else | |
1738 { | |
1739 // Remove the non-main DICOM tags from "dicom" if Case (2) | |
1740 // was used, for consistency with Case (1) | |
1741 | |
1742 DicomMap mainDicomTags; | |
1743 mainDicomTags.ExtractMainDicomTags(dicom); | |
1744 visitor.Visit(resources[i], instances[i], mainDicomTags, dicomAsJson.get()); | |
1745 } | |
1746 | |
1747 countResults ++; | |
1748 } | |
1749 } | |
1750 } | |
1751 } | |
1752 | |
1753 if (complete) | |
1754 { | |
1755 visitor.MarkAsComplete(); | |
1756 } | |
1757 | |
1758 LOG(INFO) << "Number of matching resources: " << countResults; | |
1759 } | |
1760 | |
1761 bool ServerContext::LookupOrReconstructMetadata(std::string& target, | 1534 bool ServerContext::LookupOrReconstructMetadata(std::string& target, |
1762 const std::string& publicId, | 1535 const std::string& publicId, |
1763 ResourceType level, | 1536 ResourceType level, |
1764 MetadataType metadata) | 1537 MetadataType metadata) |
1765 { | 1538 { |