Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancWebDav.cpp @ 5706:1404a80dd461 find-refactoring-clean
integration find-refactoring->find-refactoring-clean
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Jul 2024 17:54:29 +0200 |
parents | 0c2f0d72d143 eb56ee3c5d63 |
children | c8d21a09aae6 |
comparison
equal
deleted
inserted
replaced
5704:0c2f0d72d143 | 5706:1404a80dd461 |
---|---|
176 } | 176 } |
177 } | 177 } |
178 }; | 178 }; |
179 | 179 |
180 | 180 |
181 class OrthancWebDav::DicomFileVisitor : public ServerContext::ILookupVisitor | 181 class OrthancWebDav::DicomFileVisitorV2 : public ResourceFinder::IVisitor |
182 { | 182 { |
183 private: | 183 private: |
184 ServerContext& context_; | 184 ServerContext& context_; |
185 bool success_; | 185 bool success_; |
186 std::string& target_; | 186 std::string& target_; |
187 boost::posix_time::ptime& time_; | 187 boost::posix_time::ptime& time_; |
188 | 188 |
189 public: | 189 public: |
190 DicomFileVisitor(ServerContext& context, | 190 DicomFileVisitorV2(ServerContext& context, |
191 std::string& target, | 191 std::string& target, |
192 boost::posix_time::ptime& time) : | 192 boost::posix_time::ptime& time) : |
193 context_(context), | 193 context_(context), |
194 success_(false), | 194 success_(false), |
195 target_(target), | 195 target_(target), |
196 time_(time) | 196 time_(time) |
197 { | 197 { |
200 bool IsSuccess() const | 200 bool IsSuccess() const |
201 { | 201 { |
202 return success_; | 202 return success_; |
203 } | 203 } |
204 | 204 |
205 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
206 { | |
207 return false; // (*) | |
208 } | |
209 | |
210 virtual void MarkAsComplete() ORTHANC_OVERRIDE | 205 virtual void MarkAsComplete() ORTHANC_OVERRIDE |
211 { | 206 { |
212 } | 207 } |
213 | 208 |
214 virtual void Visit(const std::string& publicId, | 209 virtual void Apply(const FindResponse::Resource& resource, |
215 const std::string& instanceId /* unused */, | 210 const DicomMap& requestedTags) ORTHANC_OVERRIDE |
216 const DicomMap& mainDicomTags, | |
217 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
218 { | 211 { |
219 if (success_) | 212 if (success_) |
220 { | 213 { |
221 success_ = false; // Two matches => Error | 214 success_ = false; // Two matches => Error |
222 } | 215 } |
223 else | 216 else |
224 { | 217 { |
225 LookupTime(time_, context_, publicId, ResourceType_Instance, MetadataType_Instance_ReceptionDate); | 218 std::string s; |
226 context_.ReadDicom(target_, publicId); | 219 if (resource.LookupMetadata(s, ResourceType_Instance, MetadataType_Instance_ReceptionDate)) |
220 { | |
221 ParseTime(time_, s); | |
222 } | |
223 else | |
224 { | |
225 time_ = GetNow(); | |
226 } | |
227 | |
228 context_.ReadDicom(target_, resource.GetIdentifier()); | |
227 success_ = true; | 229 success_ = true; |
228 } | 230 } |
229 } | 231 } |
230 }; | 232 }; |
231 | 233 |
232 | 234 |
233 class OrthancWebDav::OrthancJsonVisitor : public ServerContext::ILookupVisitor | 235 class OrthancWebDav::OrthancJsonVisitor : public ServerContext::ILookupVisitor |
234 { | 236 { |
235 private: | 237 private: |
236 ServerContext& context_; | 238 ServerContext& context_; |
962 { | 964 { |
963 private: | 965 private: |
964 std::string year_; | 966 std::string year_; |
965 std::string month_; | 967 std::string month_; |
966 | 968 |
967 class Visitor : public ServerContext::ILookupVisitor | 969 class Visitor : public ResourceFinder::IVisitor |
968 { | 970 { |
969 private: | 971 private: |
970 std::list<std::string>& resources_; | 972 std::list<std::string>& resources_; |
971 | 973 |
972 public: | 974 public: |
973 explicit Visitor(std::list<std::string>& resources) : | 975 explicit Visitor(std::list<std::string>& resources) : |
974 resources_(resources) | 976 resources_(resources) |
975 { | 977 { |
976 } | 978 } |
977 | 979 |
978 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
979 { | |
980 return false; // (*) | |
981 } | |
982 | |
983 virtual void MarkAsComplete() ORTHANC_OVERRIDE | 980 virtual void MarkAsComplete() ORTHANC_OVERRIDE |
984 { | 981 { |
985 } | 982 } |
986 | 983 |
987 virtual void Visit(const std::string& publicId, | 984 virtual void Apply(const FindResponse::Resource& resource, |
988 const std::string& instanceId /* unused */, | 985 const DicomMap& requestedTags) ORTHANC_OVERRIDE |
989 const DicomMap& mainDicomTags, | 986 { |
990 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | 987 resources_.push_back(resource.GetIdentifier()); |
991 { | |
992 resources_.push_back(publicId); | |
993 } | 988 } |
994 }; | 989 }; |
995 | 990 |
996 protected: | 991 protected: |
997 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE | 992 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE |
999 DatabaseLookup query; | 994 DatabaseLookup query; |
1000 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + month_ + "01-" + year_ + month_ + "31", | 995 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + month_ + "01-" + year_ + month_ + "31", |
1001 true /* case sensitive */, true /* mandatory tag */); | 996 true /* case sensitive */, true /* mandatory tag */); |
1002 | 997 |
1003 Visitor visitor(resources); | 998 Visitor visitor(resources); |
1004 GetContext().Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | 999 |
1000 ResourceFinder finder(ResourceType_Study, false /* no expand */); | |
1001 finder.SetDatabaseLookup(query); | |
1002 finder.Execute(visitor, GetContext()); | |
1005 } | 1003 } |
1006 | 1004 |
1007 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE | 1005 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE |
1008 { | 1006 { |
1009 return new SingleDicomResource(GetContext(), ResourceType_Series, resource, GetTemplates()); | 1007 return new SingleDicomResource(GetContext(), ResourceType_Series, resource, GetTemplates()); |
1032 private: | 1030 private: |
1033 ServerContext& context_; | 1031 ServerContext& context_; |
1034 std::string year_; | 1032 std::string year_; |
1035 const Templates& templates_; | 1033 const Templates& templates_; |
1036 | 1034 |
1037 class Visitor : public ServerContext::ILookupVisitor | 1035 class Visitor : public ResourceFinder::IVisitor |
1038 { | 1036 { |
1039 private: | 1037 private: |
1040 std::set<std::string> months_; | 1038 std::set<std::string> months_; |
1041 | 1039 |
1042 public: | 1040 public: |
1043 const std::set<std::string>& GetMonths() const | 1041 const std::set<std::string>& GetMonths() const |
1044 { | 1042 { |
1045 return months_; | 1043 return months_; |
1046 } | 1044 } |
1047 | 1045 |
1048 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
1049 { | |
1050 return false; // (*) | |
1051 } | |
1052 | |
1053 virtual void MarkAsComplete() ORTHANC_OVERRIDE | 1046 virtual void MarkAsComplete() ORTHANC_OVERRIDE |
1054 { | 1047 { |
1055 } | 1048 } |
1056 | 1049 |
1057 virtual void Visit(const std::string& publicId, | 1050 virtual void Apply(const FindResponse::Resource& resource, |
1058 const std::string& instanceId /* unused */, | 1051 const DicomMap& requestedTags) ORTHANC_OVERRIDE |
1059 const DicomMap& mainDicomTags, | 1052 { |
1060 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | 1053 DicomMap mainDicomTags; |
1061 { | 1054 resource.GetMainDicomTags(mainDicomTags, ResourceType_Study); |
1055 | |
1062 std::string s; | 1056 std::string s; |
1063 if (mainDicomTags.LookupStringValue(s, DICOM_TAG_STUDY_DATE, false) && | 1057 if (mainDicomTags.LookupStringValue(s, DICOM_TAG_STUDY_DATE, false) && |
1064 s.size() == 8) | 1058 s.size() == 8) |
1065 { | 1059 { |
1066 months_.insert(s.substr(4, 2)); // Get the month from "YYYYMMDD" | 1060 months_.insert(s.substr(4, 2)); // Get the month from "YYYYMMDD" |
1078 DatabaseLookup query; | 1072 DatabaseLookup query; |
1079 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + "0101-" + year_ + "1231", | 1073 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + "0101-" + year_ + "1231", |
1080 true /* case sensitive */, true /* mandatory tag */); | 1074 true /* case sensitive */, true /* mandatory tag */); |
1081 | 1075 |
1082 Visitor visitor; | 1076 Visitor visitor; |
1083 context_.Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | 1077 |
1078 ResourceFinder finder(ResourceType_Study, false /* no expand */); | |
1079 finder.SetDatabaseLookup(query); | |
1080 finder.Execute(visitor, context_); | |
1084 | 1081 |
1085 for (std::set<std::string>::const_iterator it = visitor.GetMonths().begin(); | 1082 for (std::set<std::string>::const_iterator it = visitor.GetMonths().begin(); |
1086 it != visitor.GetMonths().end(); ++it) | 1083 it != visitor.GetMonths().end(); ++it) |
1087 { | 1084 { |
1088 target.AddResource(new IWebDavBucket::Folder(year_ + "-" + *it)); | 1085 target.AddResource(new IWebDavBucket::Folder(year_ + "-" + *it)); |
1172 { | 1169 { |
1173 } | 1170 } |
1174 }; | 1171 }; |
1175 | 1172 |
1176 | 1173 |
1177 class OrthancWebDav::DicomDeleteVisitor : public ServerContext::ILookupVisitor | 1174 class OrthancWebDav::DicomDeleteVisitor : public ResourceFinder::IVisitor |
1178 { | 1175 { |
1179 private: | 1176 private: |
1180 ServerContext& context_; | 1177 ServerContext& context_; |
1181 ResourceType level_; | 1178 ResourceType level_; |
1182 | 1179 |
1186 context_(context), | 1183 context_(context), |
1187 level_(level) | 1184 level_(level) |
1188 { | 1185 { |
1189 } | 1186 } |
1190 | 1187 |
1191 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
1192 { | |
1193 return false; // (*) | |
1194 } | |
1195 | |
1196 virtual void MarkAsComplete() ORTHANC_OVERRIDE | 1188 virtual void MarkAsComplete() ORTHANC_OVERRIDE |
1197 { | 1189 { |
1198 } | 1190 } |
1199 | 1191 |
1200 virtual void Visit(const std::string& publicId, | 1192 virtual void Apply(const FindResponse::Resource& resource, |
1201 const std::string& instanceId /* unused */, | 1193 const DicomMap& requestedTags) ORTHANC_OVERRIDE |
1202 const DicomMap& mainDicomTags /* unused */, | |
1203 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
1204 { | 1194 { |
1205 Json::Value info; | 1195 Json::Value info; |
1206 context_.DeleteResource(info, publicId, level_); | 1196 context_.DeleteResource(info, resource.GetIdentifier(), level_); |
1207 } | 1197 } |
1208 }; | 1198 }; |
1209 | 1199 |
1210 | 1200 |
1211 void OrthancWebDav::AddVirtualFile(Collection& collection, | 1201 void OrthancWebDav::AddVirtualFile(Collection& collection, |
1507 return false; | 1497 return false; |
1508 } | 1498 } |
1509 } | 1499 } |
1510 | 1500 |
1511 | 1501 |
1502 static bool GetOrthancJson(std::string& target, | |
1503 ServerContext& context, | |
1504 ResourceType level, | |
1505 const DatabaseLookup& query) | |
1506 { | |
1507 ResourceFinder finder(level, true /* expand */); | |
1508 finder.SetDatabaseLookup(query); | |
1509 | |
1510 Json::Value expanded; | |
1511 finder.Execute(expanded, context); | |
1512 | |
1513 if (expanded.size() != 1) | |
1514 { | |
1515 return false; | |
1516 } | |
1517 else | |
1518 { | |
1519 target = expanded[0].toStyledString(); | |
1520 | |
1521 // Replace UNIX newlines with DOS newlines | |
1522 boost::replace_all(target, "\n", "\r\n"); | |
1523 | |
1524 return true; | |
1525 } | |
1526 } | |
1527 | |
1528 | |
1512 bool OrthancWebDav::GetFileContent(MimeType& mime, | 1529 bool OrthancWebDav::GetFileContent(MimeType& mime, |
1513 std::string& content, | 1530 std::string& content, |
1514 boost::posix_time::ptime& modificationTime, | 1531 boost::posix_time::ptime& modificationTime, |
1515 const UriComponents& path) | 1532 const UriComponents& path) |
1516 { | 1533 { |
1524 path[2] == STUDY_INFO) | 1541 path[2] == STUDY_INFO) |
1525 { | 1542 { |
1526 DatabaseLookup query; | 1543 DatabaseLookup query; |
1527 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | 1544 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], |
1528 true /* case sensitive */, true /* mandatory tag */); | 1545 true /* case sensitive */, true /* mandatory tag */); |
1529 | |
1530 OrthancJsonVisitor visitor(context_, content, ResourceType_Study); | |
1531 context_.Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | |
1532 | 1546 |
1533 mime = MimeType_Json; | 1547 mime = MimeType_Json; |
1534 return visitor.IsSuccess(); | 1548 return GetOrthancJson(content, context_, ResourceType_Study, query); |
1535 } | 1549 } |
1536 else if (path.size() == 4 && | 1550 else if (path.size() == 4 && |
1537 path[3] == SERIES_INFO) | 1551 path[3] == SERIES_INFO) |
1538 { | 1552 { |
1539 DatabaseLookup query; | 1553 DatabaseLookup query; |
1540 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | 1554 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], |
1541 true /* case sensitive */, true /* mandatory tag */); | 1555 true /* case sensitive */, true /* mandatory tag */); |
1542 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | 1556 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], |
1543 true /* case sensitive */, true /* mandatory tag */); | 1557 true /* case sensitive */, true /* mandatory tag */); |
1544 | 1558 |
1545 OrthancJsonVisitor visitor(context_, content, ResourceType_Series); | |
1546 context_.Apply(visitor, query, ResourceType_Series, 0 /* since */, 0 /* no limit */); | |
1547 | |
1548 mime = MimeType_Json; | 1559 mime = MimeType_Json; |
1549 return visitor.IsSuccess(); | 1560 return GetOrthancJson(content, context_, ResourceType_Series, query); |
1550 } | 1561 } |
1551 else if (path.size() == 4 && | 1562 else if (path.size() == 4 && |
1552 boost::ends_with(path[3], ".dcm")) | 1563 boost::ends_with(path[3], ".dcm")) |
1553 { | 1564 { |
1554 const std::string sopInstanceUid = path[3].substr(0, path[3].size() - 4); | 1565 const std::string sopInstanceUid = path[3].substr(0, path[3].size() - 4); |
1559 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | 1570 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], |
1560 true /* case sensitive */, true /* mandatory tag */); | 1571 true /* case sensitive */, true /* mandatory tag */); |
1561 query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, | 1572 query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, |
1562 true /* case sensitive */, true /* mandatory tag */); | 1573 true /* case sensitive */, true /* mandatory tag */); |
1563 | 1574 |
1564 DicomFileVisitor visitor(context_, content, modificationTime); | |
1565 context_.Apply(visitor, query, ResourceType_Instance, 0 /* since */, 0 /* no limit */); | |
1566 | |
1567 mime = MimeType_Dicom; | 1575 mime = MimeType_Dicom; |
1576 | |
1577 ResourceFinder finder(ResourceType_Instance, false /* no expand */); | |
1578 finder.SetDatabaseLookup(query); | |
1579 finder.SetRetrieveMetadata(true); | |
1580 finder.SetRetrieveAttachments(true); | |
1581 | |
1582 DicomFileVisitorV2 visitor(context_, content, modificationTime); | |
1583 finder.Execute(visitor, context_); | |
1584 | |
1568 return visitor.IsSuccess(); | 1585 return visitor.IsSuccess(); |
1569 } | 1586 } |
1570 else | 1587 else |
1571 { | 1588 { |
1572 return false; | 1589 return false; |
1684 return false; | 1701 return false; |
1685 } | 1702 } |
1686 } | 1703 } |
1687 | 1704 |
1688 DicomDeleteVisitor visitor(context_, level); | 1705 DicomDeleteVisitor visitor(context_, level); |
1689 context_.Apply(visitor, query, level, 0 /* since */, 0 /* no limit */); | 1706 |
1707 ResourceFinder finder(level, false /* no expand */); | |
1708 finder.SetDatabaseLookup(query); | |
1709 finder.Execute(visitor, context_); | |
1690 return true; | 1710 return true; |
1691 } | 1711 } |
1692 else | 1712 else |
1693 { | 1713 { |
1694 return false; // read-only | 1714 return false; // read-only |