Mercurial > hg > orthanc
comparison OrthancServer/Sources/main.cpp @ 4237:f39d162ba7e9
sharing more code
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 09 Oct 2020 10:06:20 +0200 |
parents | 5639ffda467b |
children | c007fb7c8395 |
comparison
equal
deleted
inserted
replaced
4236:5639ffda467b | 4237:f39d162ba7e9 |
---|---|
1219 const UriComponents& path) = 0; | 1219 const UriComponents& path) = 0; |
1220 }; | 1220 }; |
1221 | 1221 |
1222 | 1222 |
1223 | 1223 |
1224 class InstancesNode : public INode | 1224 class InstancesOfSeries : public INode |
1225 { | 1225 { |
1226 private: | 1226 private: |
1227 ServerContext& context_; | 1227 ServerContext& context_; |
1228 std::string parentSeries_; | 1228 std::string parentSeries_; |
1229 | 1229 |
1230 public: | 1230 public: |
1231 InstancesNode(ServerContext& context, | 1231 InstancesOfSeries(ServerContext& context, |
1232 const std::string& parentSeries) : | 1232 const std::string& parentSeries) : |
1233 context_(context), | 1233 context_(context), |
1234 parentSeries_(parentSeries) | 1234 parentSeries_(parentSeries) |
1235 { | 1235 { |
1236 } | 1236 } |
1237 | 1237 |
1345 return child->second; | 1345 return child->second; |
1346 } | 1346 } |
1347 } | 1347 } |
1348 | 1348 |
1349 protected: | 1349 protected: |
1350 void RemoveSubfolder(const std::string& path) | |
1351 { | |
1352 Children::iterator child = children_.find(path); | |
1353 if (child != children_.end()) | |
1354 { | |
1355 assert(child->second != NULL); | |
1356 delete child->second; | |
1357 children_.erase(child); | |
1358 } | |
1359 } | |
1360 | |
1350 virtual void Refresh() = 0; | 1361 virtual void Refresh() = 0; |
1351 | 1362 |
1352 virtual bool ListContent(IWebDavBucket::Collection& target) = 0; | 1363 virtual bool ListSubfolders(IWebDavBucket::Collection& target) = 0; |
1353 | 1364 |
1354 virtual INode* CreateChild(const std::string& path) = 0; | 1365 virtual INode* CreateChild(const std::string& path) = 0; |
1355 | 1366 |
1356 public: | 1367 public: |
1357 virtual ~InternalNode() | 1368 virtual ~InternalNode() |
1369 { | 1380 { |
1370 Refresh(); | 1381 Refresh(); |
1371 | 1382 |
1372 if (path.empty()) | 1383 if (path.empty()) |
1373 { | 1384 { |
1374 return ListContent(target); | 1385 return ListSubfolders(target); |
1375 } | 1386 } |
1376 else | 1387 else |
1377 { | 1388 { |
1378 // Recursivity | 1389 // Recursivity |
1379 INode* child = GetChild(path[0]); | 1390 INode* child = GetChild(path[0]); |
1395 const UriComponents& path) | 1406 const UriComponents& path) |
1396 ORTHANC_OVERRIDE ORTHANC_FINAL | 1407 ORTHANC_OVERRIDE ORTHANC_FINAL |
1397 { | 1408 { |
1398 if (path.empty()) | 1409 if (path.empty()) |
1399 { | 1410 { |
1400 return false; | 1411 return false; // An internal node doesn't correspond to a file |
1401 } | 1412 } |
1402 else | 1413 else |
1403 { | 1414 { |
1404 // Recursivity | 1415 // Recursivity |
1405 Refresh(); | 1416 Refresh(); |
1417 } | 1428 } |
1418 } | 1429 } |
1419 }; | 1430 }; |
1420 | 1431 |
1421 | 1432 |
1422 class ResourcesNode : public INode | 1433 class ListOfResources : public InternalNode |
1423 { | 1434 { |
1424 private: | 1435 private: |
1425 typedef std::map<std::string, INode*> Children; | |
1426 | |
1427 ServerContext& context_; | 1436 ServerContext& context_; |
1428 const Templates& templates_; | 1437 const Templates& templates_; |
1429 std::unique_ptr<ResourcesIndex> index_; | 1438 std::unique_ptr<ResourcesIndex> index_; |
1430 MetadataType timeMetadata_; | 1439 MetadataType timeMetadata_; |
1431 Children children_; // Maps paths to subnodes | 1440 |
1432 | 1441 protected: |
1433 void Refresh() | 1442 virtual void Refresh() ORTHANC_OVERRIDE ORTHANC_FINAL |
1434 { | 1443 { |
1435 std::list<std::string> resources; | 1444 std::list<std::string> resources; |
1436 GetCurrentResources(resources); | 1445 GetCurrentResources(resources); |
1437 | 1446 |
1438 std::set<std::string> removedPaths; | 1447 std::set<std::string> removedPaths; |
1440 | 1449 |
1441 // Remove the children whose associated resource doesn't exist anymore | 1450 // Remove the children whose associated resource doesn't exist anymore |
1442 for (std::set<std::string>::const_iterator | 1451 for (std::set<std::string>::const_iterator |
1443 it = removedPaths.begin(); it != removedPaths.end(); ++it) | 1452 it = removedPaths.begin(); it != removedPaths.end(); ++it) |
1444 { | 1453 { |
1445 Children::iterator child = children_.find(*it); | 1454 RemoveSubfolder(*it); |
1446 if (child != children_.end()) | 1455 } |
1447 { | 1456 } |
1448 assert(child->second != NULL); | 1457 |
1449 delete child->second; | 1458 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE ORTHANC_FINAL |
1450 children_.erase(child); | 1459 { |
1451 } | |
1452 } | |
1453 } | |
1454 | |
1455 INode* GetChild(const std::string& path) // Don't free the resulting pointer! | |
1456 { | |
1457 Children::iterator child = children_.find(path); | |
1458 if (child == children_.end()) | |
1459 { | |
1460 INode* child = CreateChild(path); | |
1461 if (child == NULL) | |
1462 { | |
1463 return NULL; | |
1464 } | |
1465 else | |
1466 { | |
1467 children_[path] = child; | |
1468 return child; | |
1469 } | |
1470 } | |
1471 else | |
1472 { | |
1473 assert(child->second != NULL); | |
1474 return child->second; | |
1475 } | |
1476 } | |
1477 | |
1478 protected: | |
1479 ServerContext& GetContext() const | |
1480 { | |
1481 return context_; | |
1482 } | |
1483 | |
1484 virtual void GetCurrentResources(std::list<std::string>& resources) = 0; | |
1485 | |
1486 virtual INode* CreateChild(const std::string& path) | |
1487 { | |
1488 ResourcesIndex::Map::const_iterator resource = index_->GetPathToResource().find(path); | |
1489 if (resource == index_->GetPathToResource().end()) | |
1490 { | |
1491 return NULL; | |
1492 } | |
1493 else | |
1494 { | |
1495 return CreateResourceNode(resource->second); | |
1496 } | |
1497 } | |
1498 | |
1499 virtual INode* CreateResourceNode(const std::string& resource) = 0; | |
1500 | |
1501 public: | |
1502 ResourcesNode(ServerContext& context, | |
1503 ResourceType level, | |
1504 const Templates& templates) : | |
1505 context_(context), | |
1506 templates_(templates) | |
1507 { | |
1508 Templates::const_iterator t = templates.find(level); | |
1509 if (t == templates.end()) | |
1510 { | |
1511 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1512 } | |
1513 | |
1514 index_.reset(new ResourcesIndex(context, level, t->second)); | |
1515 | |
1516 if (level == ResourceType_Instance) | |
1517 { | |
1518 timeMetadata_ = MetadataType_Instance_ReceptionDate; | |
1519 } | |
1520 else | |
1521 { | |
1522 timeMetadata_ = MetadataType_LastUpdate; | |
1523 } | |
1524 } | |
1525 | |
1526 virtual ~ResourcesNode() | |
1527 { | |
1528 for (Children::iterator it = children_.begin(); it != children_.end(); ++it) | |
1529 { | |
1530 assert(it->second != NULL); | |
1531 delete it->second; | |
1532 } | |
1533 } | |
1534 | |
1535 ResourceType GetLevel() const | |
1536 { | |
1537 return index_->GetLevel(); | |
1538 } | |
1539 | |
1540 const Templates& GetTemplates() const | |
1541 { | |
1542 return templates_; | |
1543 } | |
1544 | |
1545 virtual bool ListCollection(IWebDavBucket::Collection& target, | |
1546 const UriComponents& path) | |
1547 ORTHANC_OVERRIDE ORTHANC_FINAL | |
1548 { | |
1549 Refresh(); | |
1550 | |
1551 if (index_->GetLevel() == ResourceType_Instance) | 1460 if (index_->GetLevel() == ResourceType_Instance) |
1552 { | 1461 { |
1553 // Not a collection, no subfolders | 1462 // Not a collection, no subfolders |
1554 return false; | 1463 return false; |
1555 } | 1464 } |
1556 else if (path.empty()) | 1465 else |
1557 { | 1466 { |
1558 const ResourcesIndex::Map& paths = index_->GetPathToResource(); | 1467 const ResourcesIndex::Map& paths = index_->GetPathToResource(); |
1559 | 1468 |
1560 for (ResourcesIndex::Map::const_iterator it = paths.begin(); it != paths.end(); ++it) | 1469 for (ResourcesIndex::Map::const_iterator it = paths.begin(); it != paths.end(); ++it) |
1561 { | 1470 { |
1567 target.AddResource(resource.release()); | 1476 target.AddResource(resource.release()); |
1568 } | 1477 } |
1569 | 1478 |
1570 return true; | 1479 return true; |
1571 } | 1480 } |
1481 } | |
1482 | |
1483 virtual INode* CreateChild(const std::string& path) ORTHANC_OVERRIDE ORTHANC_FINAL | |
1484 { | |
1485 ResourcesIndex::Map::const_iterator resource = index_->GetPathToResource().find(path); | |
1486 if (resource == index_->GetPathToResource().end()) | |
1487 { | |
1488 return NULL; | |
1489 } | |
1572 else | 1490 else |
1573 { | 1491 { |
1574 // Recursivity | 1492 return CreateResourceNode(resource->second); |
1575 INode* child = GetChild(path[0]); | 1493 } |
1576 if (child == NULL) | 1494 } |
1577 { | 1495 |
1578 return false; | 1496 ServerContext& GetContext() const |
1579 } | 1497 { |
1580 else | 1498 return context_; |
1581 { | 1499 } |
1582 UriComponents subpath(path.begin() + 1, path.end()); | 1500 |
1583 return child->ListCollection(target, subpath); | 1501 virtual void GetCurrentResources(std::list<std::string>& resources) = 0; |
1584 } | 1502 |
1585 } | 1503 virtual INode* CreateResourceNode(const std::string& resource) = 0; |
1586 } | 1504 |
1587 | 1505 public: |
1588 virtual bool GetFileContent(MimeType& mime, | 1506 ListOfResources(ServerContext& context, |
1589 std::string& content, | 1507 ResourceType level, |
1590 boost::posix_time::ptime& time, | 1508 const Templates& templates) : |
1591 const UriComponents& path) | 1509 context_(context), |
1592 ORTHANC_OVERRIDE ORTHANC_FINAL | 1510 templates_(templates) |
1593 { | 1511 { |
1594 if (path.empty()) | 1512 Templates::const_iterator t = templates.find(level); |
1595 { | 1513 if (t == templates.end()) |
1596 return false; | 1514 { |
1515 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1516 } | |
1517 | |
1518 index_.reset(new ResourcesIndex(context, level, t->second)); | |
1519 | |
1520 if (level == ResourceType_Instance) | |
1521 { | |
1522 timeMetadata_ = MetadataType_Instance_ReceptionDate; | |
1597 } | 1523 } |
1598 else | 1524 else |
1599 { | 1525 { |
1600 // Recursivity | 1526 timeMetadata_ = MetadataType_LastUpdate; |
1601 Refresh(); | 1527 } |
1602 | 1528 } |
1603 INode* child = GetChild(path[0]); | 1529 |
1604 if (child == NULL) | 1530 ResourceType GetLevel() const |
1605 { | 1531 { |
1606 return false; | 1532 return index_->GetLevel(); |
1607 } | 1533 } |
1608 else | 1534 |
1609 { | 1535 const Templates& GetTemplates() const |
1610 UriComponents subpath(path.begin() + 1, path.end()); | 1536 { |
1611 return child->GetFileContent(mime, content, time, subpath); | 1537 return templates_; |
1612 } | |
1613 } | |
1614 } | 1538 } |
1615 }; | 1539 }; |
1616 | 1540 |
1617 | 1541 |
1618 | 1542 |
1619 class ResourceChildrenNode : public ResourcesNode | 1543 class ResourceChildrenNode : public ListOfResources |
1620 { | 1544 { |
1621 private: | 1545 private: |
1622 std::string parentId_; | 1546 std::string parentId_; |
1623 | 1547 |
1624 protected: | 1548 protected: |
1641 { | 1565 { |
1642 return NULL; | 1566 return NULL; |
1643 } | 1567 } |
1644 else if (GetLevel() == ResourceType_Series) | 1568 else if (GetLevel() == ResourceType_Series) |
1645 { | 1569 { |
1646 return new InstancesNode(GetContext(), resource); | 1570 return new InstancesOfSeries(GetContext(), resource); |
1647 } | 1571 } |
1648 else | 1572 else |
1649 { | 1573 { |
1650 ResourceType l = GetChildResourceType(GetLevel()); | 1574 ResourceType l = GetChildResourceType(GetLevel()); |
1651 return new ResourceChildrenNode(GetContext(), l, resource, GetTemplates()); | 1575 return new ResourceChildrenNode(GetContext(), l, resource, GetTemplates()); |
1655 public: | 1579 public: |
1656 ResourceChildrenNode(ServerContext& context, | 1580 ResourceChildrenNode(ServerContext& context, |
1657 ResourceType level, | 1581 ResourceType level, |
1658 const std::string& parentId, | 1582 const std::string& parentId, |
1659 const Templates& templates) : | 1583 const Templates& templates) : |
1660 ResourcesNode(context, level, templates), | 1584 ListOfResources(context, level, templates), |
1661 parentId_(parentId) | 1585 parentId_(parentId) |
1662 { | 1586 { |
1663 } | 1587 } |
1664 }; | 1588 }; |
1665 | 1589 |
1666 | 1590 |
1667 class RootNode : public ResourcesNode | 1591 class RootNode : public ListOfResources |
1668 { | 1592 { |
1669 protected: | 1593 protected: |
1670 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE | 1594 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE |
1671 { | 1595 { |
1672 GetContext().GetIndex().GetAllUuids(resources, GetLevel()); | 1596 GetContext().GetIndex().GetAllUuids(resources, GetLevel()); |
1674 | 1598 |
1675 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE | 1599 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE |
1676 { | 1600 { |
1677 if (GetLevel() == ResourceType_Series) | 1601 if (GetLevel() == ResourceType_Series) |
1678 { | 1602 { |
1679 return new InstancesNode(GetContext(), resource); | 1603 return new InstancesOfSeries(GetContext(), resource); |
1680 } | 1604 } |
1681 else | 1605 else |
1682 { | 1606 { |
1683 ResourceType l = GetChildResourceType(GetLevel()); | 1607 ResourceType l = GetChildResourceType(GetLevel()); |
1684 return new ResourceChildrenNode(GetContext(), l, resource, GetTemplates()); | 1608 return new ResourceChildrenNode(GetContext(), l, resource, GetTemplates()); |
1687 | 1611 |
1688 public: | 1612 public: |
1689 RootNode(ServerContext& context, | 1613 RootNode(ServerContext& context, |
1690 ResourceType level, | 1614 ResourceType level, |
1691 const Templates& templates) : | 1615 const Templates& templates) : |
1692 ResourcesNode(context, level, templates) | 1616 ListOfResources(context, level, templates) |
1693 { | 1617 { |
1694 } | 1618 } |
1695 }; | 1619 }; |
1696 | 1620 |
1697 | 1621 |
1698 | 1622 |
1699 class StudyMonthsNode : public InternalNode | 1623 class ListOfStudiesByMonth : public InternalNode |
1700 { | 1624 { |
1701 private: | 1625 private: |
1702 ServerContext& context_; | 1626 ServerContext& context_; |
1703 std::string year_; | 1627 std::string year_; |
1704 const Templates& templates_; | 1628 const Templates& templates_; |
1744 protected: | 1668 protected: |
1745 virtual void Refresh() ORTHANC_OVERRIDE | 1669 virtual void Refresh() ORTHANC_OVERRIDE |
1746 { | 1670 { |
1747 } | 1671 } |
1748 | 1672 |
1749 virtual bool ListContent(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE | 1673 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE |
1750 { | 1674 { |
1751 DatabaseLookup query; | 1675 DatabaseLookup query; |
1752 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + "0101-" + year_ + "1231", | 1676 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + "0101-" + year_ + "1231", |
1753 true /* case sensitive */, true /* mandatory tag */); | 1677 true /* case sensitive */, true /* mandatory tag */); |
1754 | 1678 |
1768 { | 1692 { |
1769 return NULL; | 1693 return NULL; |
1770 } | 1694 } |
1771 | 1695 |
1772 public: | 1696 public: |
1773 StudyMonthsNode(ServerContext& context, | 1697 ListOfStudiesByMonth(ServerContext& context, |
1774 const std::string& year, | 1698 const std::string& year, |
1775 const Templates& templates) : | 1699 const Templates& templates) : |
1776 context_(context), | 1700 context_(context), |
1777 year_(year), | 1701 year_(year), |
1778 templates_(templates) | 1702 templates_(templates) |
1779 { | 1703 { |
1780 } | 1704 } |
1781 }; | 1705 }; |
1782 | 1706 |
1783 | 1707 |
1784 class StudyYearsNode : public InternalNode | 1708 class ListOfStudiesByYear : public InternalNode |
1785 { | 1709 { |
1786 private: | 1710 private: |
1787 ServerContext& context_; | 1711 ServerContext& context_; |
1788 const Templates& templates_; | 1712 const Templates& templates_; |
1789 | 1713 |
1790 protected: | 1714 protected: |
1791 virtual void Refresh() ORTHANC_OVERRIDE | 1715 virtual void Refresh() ORTHANC_OVERRIDE |
1792 { | 1716 { |
1793 } | 1717 } |
1794 | 1718 |
1795 virtual bool ListContent(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE | 1719 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE |
1796 { | 1720 { |
1797 std::list<std::string> resources; | 1721 std::list<std::string> resources; |
1798 context_.GetIndex().GetAllUuids(resources, ResourceType_Study); | 1722 context_.GetIndex().GetAllUuids(resources, ResourceType_Study); |
1799 | 1723 |
1800 std::set<std::string> years; | 1724 std::set<std::string> years; |
1819 return true; | 1743 return true; |
1820 } | 1744 } |
1821 | 1745 |
1822 virtual INode* CreateChild(const std::string& path) ORTHANC_OVERRIDE | 1746 virtual INode* CreateChild(const std::string& path) ORTHANC_OVERRIDE |
1823 { | 1747 { |
1824 return new StudyMonthsNode(context_, path, templates_); | 1748 return new ListOfStudiesByMonth(context_, path, templates_); |
1825 } | 1749 } |
1826 | 1750 |
1827 public: | 1751 public: |
1828 StudyYearsNode(ServerContext& context, | 1752 ListOfStudiesByYear(ServerContext& context, |
1829 const Templates& templates) : | 1753 const Templates& templates) : |
1830 context_(context), | 1754 context_(context), |
1831 templates_(templates) | 1755 templates_(templates) |
1832 { | 1756 { |
1833 } | 1757 } |
1834 }; | 1758 }; |
1853 studiesTemplates_[ResourceType_Study] = "{{PatientID}} - {{PatientName}} - {{StudyDescription}}"; | 1777 studiesTemplates_[ResourceType_Study] = "{{PatientID}} - {{PatientName}} - {{StudyDescription}}"; |
1854 studiesTemplates_[ResourceType_Series] = patientsTemplates_[ResourceType_Series]; | 1778 studiesTemplates_[ResourceType_Series] = patientsTemplates_[ResourceType_Series]; |
1855 | 1779 |
1856 patients_.reset(new RootNode(context, ResourceType_Patient, patientsTemplates_)); | 1780 patients_.reset(new RootNode(context, ResourceType_Patient, patientsTemplates_)); |
1857 studies_.reset(new RootNode(context, ResourceType_Study, studiesTemplates_)); | 1781 studies_.reset(new RootNode(context, ResourceType_Study, studiesTemplates_)); |
1858 dates_.reset(new StudyYearsNode(context, studiesTemplates_)); | 1782 dates_.reset(new ListOfStudiesByYear(context, studiesTemplates_)); |
1859 } | 1783 } |
1860 | 1784 |
1861 virtual bool IsExistingFolder(const UriComponents& path) ORTHANC_OVERRIDE | 1785 virtual bool IsExistingFolder(const UriComponents& path) ORTHANC_OVERRIDE |
1862 { | 1786 { |
1863 if (path.empty()) | 1787 if (path.empty()) |