Mercurial > hg > orthanc
comparison OrthancServer/Sources/main.cpp @ 4231:290ffcb0a147
publishing the DICOM hierarchy as WebDAV bucket
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 06 Oct 2020 20:55:16 +0200 |
parents | b313a0001893 |
children | 688435755466 |
comparison
equal
deleted
inserted
replaced
4230:b313a0001893 | 4231:290ffcb0a147 |
---|---|
56 #include "ServerJobs/StorageCommitmentScpJob.h" | 56 #include "ServerJobs/StorageCommitmentScpJob.h" |
57 #include "ServerToolbox.h" | 57 #include "ServerToolbox.h" |
58 #include "StorageCommitmentReports.h" | 58 #include "StorageCommitmentReports.h" |
59 | 59 |
60 #include "../../OrthancFramework/Sources/HttpServer/WebDavStorage.h" // TODO | 60 #include "../../OrthancFramework/Sources/HttpServer/WebDavStorage.h" // TODO |
61 #include "Search/DatabaseLookup.h" // TODO | |
61 | 62 |
62 | 63 |
63 using namespace Orthanc; | 64 using namespace Orthanc; |
64 | 65 |
65 | 66 |
761 } | 762 } |
762 | 763 |
763 virtual void Stop() ORTHANC_OVERRIDE | 764 virtual void Stop() ORTHANC_OVERRIDE |
764 { | 765 { |
765 LOG(WARNING) << "Stopping WebDAV"; | 766 LOG(WARNING) << "Stopping WebDAV"; |
767 } | |
768 }; | |
769 | |
770 | |
771 | |
772 | |
773 | |
774 static const char* const DICOM_IDENTIFIERS = "DicomIdentifiers"; | |
775 | |
776 class DummyBucket2 : public IWebDavBucket // TODO | |
777 { | |
778 private: | |
779 ServerContext& context_; | |
780 | |
781 class DicomIdentifiersVisitor : public ServerContext::ILookupVisitor | |
782 { | |
783 private: | |
784 ServerContext& context_; | |
785 bool isComplete_; | |
786 Collection& target_; | |
787 ResourceType level_; | |
788 | |
789 public: | |
790 DicomIdentifiersVisitor(ServerContext& context, | |
791 Collection& target, | |
792 ResourceType level) : | |
793 context_(context), | |
794 isComplete_(false), | |
795 target_(target), | |
796 level_(level) | |
797 { | |
798 } | |
799 | |
800 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
801 { | |
802 return false; // (*) | |
803 } | |
804 | |
805 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
806 { | |
807 isComplete_ = true; // TODO | |
808 } | |
809 | |
810 virtual void Visit(const std::string& publicId, | |
811 const std::string& instanceId /* unused */, | |
812 const DicomMap& mainDicomTags, | |
813 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
814 { | |
815 DicomTag tag(0, 0); | |
816 switch (level_) | |
817 { | |
818 case ResourceType_Study: | |
819 tag = DICOM_TAG_STUDY_INSTANCE_UID; | |
820 break; | |
821 | |
822 case ResourceType_Series: | |
823 tag = DICOM_TAG_SERIES_INSTANCE_UID; | |
824 break; | |
825 | |
826 case ResourceType_Instance: | |
827 tag = DICOM_TAG_SOP_INSTANCE_UID; | |
828 break; | |
829 | |
830 default: | |
831 throw OrthancException(ErrorCode_InternalError); | |
832 } | |
833 | |
834 std::string s; | |
835 if (mainDicomTags.LookupStringValue(s, tag, false) && | |
836 !s.empty()) | |
837 { | |
838 if (level_ == ResourceType_Instance) | |
839 { | |
840 FileInfo info; | |
841 if (context_.GetIndex().LookupAttachment(info, publicId, FileContentType_Dicom)) | |
842 { | |
843 std::unique_ptr<File> f(new File(s + ".dcm")); | |
844 f->SetMimeType(MimeType_Dicom); | |
845 f->SetContentLength(info.GetUncompressedSize()); | |
846 target_.AddResource(f.release()); | |
847 } | |
848 } | |
849 else | |
850 { | |
851 target_.AddResource(new Folder(s)); | |
852 } | |
853 } | |
854 } | |
855 }; | |
856 | |
857 class DicomFileVisitor : public ServerContext::ILookupVisitor | |
858 { | |
859 private: | |
860 ServerContext& context_; | |
861 bool success_; | |
862 std::string& target_; | |
863 | |
864 public: | |
865 DicomFileVisitor(ServerContext& context, | |
866 std::string& target) : | |
867 context_(context), | |
868 success_(false), | |
869 target_(target) | |
870 { | |
871 } | |
872 | |
873 bool IsSuccess() const | |
874 { | |
875 return success_; | |
876 } | |
877 | |
878 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
879 { | |
880 return false; // (*) | |
881 } | |
882 | |
883 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
884 { | |
885 } | |
886 | |
887 virtual void Visit(const std::string& publicId, | |
888 const std::string& instanceId /* unused */, | |
889 const DicomMap& mainDicomTags, | |
890 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
891 { | |
892 context_.ReadDicom(target_, publicId); | |
893 success_ = true; | |
894 } | |
895 }; | |
896 | |
897 public: | |
898 DummyBucket2(ServerContext& context) : | |
899 context_(context) | |
900 { | |
901 } | |
902 | |
903 virtual bool IsExistingFolder(const UriComponents& path) ORTHANC_OVERRIDE | |
904 { | |
905 if (path.empty()) | |
906 { | |
907 return true; | |
908 } | |
909 else if (path.front() == DICOM_IDENTIFIERS && | |
910 path.size() <= 3) | |
911 { | |
912 return true; | |
913 } | |
914 else | |
915 { | |
916 return false; | |
917 } | |
918 } | |
919 | |
920 virtual bool ListCollection(Collection& collection, | |
921 const UriComponents& path) ORTHANC_OVERRIDE | |
922 { | |
923 if (path.empty()) | |
924 { | |
925 collection.AddResource(new Folder(DICOM_IDENTIFIERS)); | |
926 return true; | |
927 } | |
928 else if (path.front() == DICOM_IDENTIFIERS) | |
929 { | |
930 DatabaseLookup query; | |
931 ResourceType level; | |
932 | |
933 if (path.size() == 1) | |
934 { | |
935 level = ResourceType_Study; | |
936 } | |
937 else if (path.size() == 2) | |
938 { | |
939 level = ResourceType_Series; | |
940 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
941 true /* case sensitive */, true /* mandatory tag */); | |
942 } | |
943 else if (path.size() == 3) | |
944 { | |
945 level = ResourceType_Instance; | |
946 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
947 true /* case sensitive */, true /* mandatory tag */); | |
948 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | |
949 true /* case sensitive */, true /* mandatory tag */); | |
950 } | |
951 else | |
952 { | |
953 return false; | |
954 } | |
955 | |
956 DicomIdentifiersVisitor visitor(context_, collection, level); | |
957 context_.Apply(visitor, query, level, 0 /* since */, 100 /* limit */); | |
958 | |
959 return true; | |
960 } | |
961 else | |
962 { | |
963 return false; | |
964 } | |
965 } | |
966 | |
967 virtual bool GetFileContent(MimeType& mime, | |
968 std::string& content, | |
969 boost::posix_time::ptime& modificationTime, | |
970 const UriComponents& path) ORTHANC_OVERRIDE | |
971 { | |
972 if (path.size() == 4 && | |
973 path[0] == DICOM_IDENTIFIERS && | |
974 boost::ends_with(path[3], ".dcm")) | |
975 { | |
976 std::string sopInstanceUid = path[3]; | |
977 sopInstanceUid.resize(sopInstanceUid.size() - 4); | |
978 | |
979 mime = MimeType_Dicom; | |
980 | |
981 DatabaseLookup query; | |
982 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
983 true /* case sensitive */, true /* mandatory tag */); | |
984 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | |
985 true /* case sensitive */, true /* mandatory tag */); | |
986 query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, | |
987 true /* case sensitive */, true /* mandatory tag */); | |
988 | |
989 DicomFileVisitor visitor(context_, content); | |
990 context_.Apply(visitor, query, ResourceType_Instance, 0 /* since */, 100 /* limit */); | |
991 | |
992 return visitor.IsSuccess(); | |
993 } | |
994 else | |
995 { | |
996 return false; | |
997 } | |
998 } | |
999 | |
1000 | |
1001 virtual bool StoreFile(const std::string& content, | |
1002 const UriComponents& path) ORTHANC_OVERRIDE | |
1003 { | |
1004 return false; | |
1005 } | |
1006 | |
1007 | |
1008 virtual bool CreateFolder(const UriComponents& path) | |
1009 { | |
1010 return false; | |
1011 } | |
1012 | |
1013 virtual void Start() ORTHANC_OVERRIDE | |
1014 { | |
1015 } | |
1016 | |
1017 virtual void Stop() ORTHANC_OVERRIDE | |
1018 { | |
766 } | 1019 } |
767 }; | 1020 }; |
768 | 1021 |
769 | 1022 |
770 | 1023 |
1208 { | 1461 { |
1209 UriComponents root; // TODO | 1462 UriComponents root; // TODO |
1210 root.push_back("a"); | 1463 root.push_back("a"); |
1211 root.push_back("b"); | 1464 root.push_back("b"); |
1212 //httpServer.Register(root, new WebDavStorage(true)); | 1465 //httpServer.Register(root, new WebDavStorage(true)); |
1213 httpServer.Register(root, new DummyBucket(context, true)); | 1466 //httpServer.Register(root, new DummyBucket(context, true)); |
1467 httpServer.Register(root, new DummyBucket2(context)); | |
1214 } | 1468 } |
1215 | 1469 |
1216 if (httpServer.GetPortNumber() < 1024) | 1470 if (httpServer.GetPortNumber() < 1024) |
1217 { | 1471 { |
1218 LOG(WARNING) << "The HTTP port is privileged (" | 1472 LOG(WARNING) << "The HTTP port is privileged (" |