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())