Mercurial > hg > orthanc
changeset 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 |
files | OrthancFramework/Sources/TemporaryFile.h OrthancServer/Sources/main.cpp |
diffstat | 2 files changed, 256 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/TemporaryFile.h Tue Oct 06 18:14:26 2020 +0200 +++ b/OrthancFramework/Sources/TemporaryFile.h Tue Oct 06 20:55:16 2020 +0200 @@ -33,6 +33,7 @@ #endif #include <boost/noncopyable.hpp> +#include <stdint.h> #include <string> namespace Orthanc
--- a/OrthancServer/Sources/main.cpp Tue Oct 06 18:14:26 2020 +0200 +++ b/OrthancServer/Sources/main.cpp Tue Oct 06 20:55:16 2020 +0200 @@ -58,6 +58,7 @@ #include "StorageCommitmentReports.h" #include "../../OrthancFramework/Sources/HttpServer/WebDavStorage.h" // TODO +#include "Search/DatabaseLookup.h" // TODO using namespace Orthanc; @@ -768,6 +769,258 @@ + + +static const char* const DICOM_IDENTIFIERS = "DicomIdentifiers"; + +class DummyBucket2 : public IWebDavBucket // TODO +{ +private: + ServerContext& context_; + + class DicomIdentifiersVisitor : public ServerContext::ILookupVisitor + { + private: + ServerContext& context_; + bool isComplete_; + Collection& target_; + ResourceType level_; + + public: + DicomIdentifiersVisitor(ServerContext& context, + Collection& target, + ResourceType level) : + context_(context), + isComplete_(false), + target_(target), + level_(level) + { + } + + virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE + { + return false; // (*) + } + + virtual void MarkAsComplete() ORTHANC_OVERRIDE + { + isComplete_ = true; // TODO + } + + virtual void Visit(const std::string& publicId, + const std::string& instanceId /* unused */, + const DicomMap& mainDicomTags, + const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE + { + DicomTag tag(0, 0); + switch (level_) + { + case ResourceType_Study: + tag = DICOM_TAG_STUDY_INSTANCE_UID; + break; + + case ResourceType_Series: + tag = DICOM_TAG_SERIES_INSTANCE_UID; + break; + + case ResourceType_Instance: + tag = DICOM_TAG_SOP_INSTANCE_UID; + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + std::string s; + if (mainDicomTags.LookupStringValue(s, tag, false) && + !s.empty()) + { + if (level_ == ResourceType_Instance) + { + FileInfo info; + if (context_.GetIndex().LookupAttachment(info, publicId, FileContentType_Dicom)) + { + std::unique_ptr<File> f(new File(s + ".dcm")); + f->SetMimeType(MimeType_Dicom); + f->SetContentLength(info.GetUncompressedSize()); + target_.AddResource(f.release()); + } + } + else + { + target_.AddResource(new Folder(s)); + } + } + } + }; + + class DicomFileVisitor : public ServerContext::ILookupVisitor + { + private: + ServerContext& context_; + bool success_; + std::string& target_; + + public: + DicomFileVisitor(ServerContext& context, + std::string& target) : + context_(context), + success_(false), + target_(target) + { + } + + bool IsSuccess() const + { + return success_; + } + + virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE + { + return false; // (*) + } + + virtual void MarkAsComplete() ORTHANC_OVERRIDE + { + } + + virtual void Visit(const std::string& publicId, + const std::string& instanceId /* unused */, + const DicomMap& mainDicomTags, + const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE + { + context_.ReadDicom(target_, publicId); + success_ = true; + } + }; + +public: + DummyBucket2(ServerContext& context) : + context_(context) + { + } + + virtual bool IsExistingFolder(const UriComponents& path) ORTHANC_OVERRIDE + { + if (path.empty()) + { + return true; + } + else if (path.front() == DICOM_IDENTIFIERS && + path.size() <= 3) + { + return true; + } + else + { + return false; + } + } + + virtual bool ListCollection(Collection& collection, + const UriComponents& path) ORTHANC_OVERRIDE + { + if (path.empty()) + { + collection.AddResource(new Folder(DICOM_IDENTIFIERS)); + return true; + } + else if (path.front() == DICOM_IDENTIFIERS) + { + DatabaseLookup query; + ResourceType level; + + if (path.size() == 1) + { + level = ResourceType_Study; + } + else if (path.size() == 2) + { + level = ResourceType_Series; + query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], + true /* case sensitive */, true /* mandatory tag */); + } + else if (path.size() == 3) + { + level = ResourceType_Instance; + query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], + true /* case sensitive */, true /* mandatory tag */); + query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], + true /* case sensitive */, true /* mandatory tag */); + } + else + { + return false; + } + + DicomIdentifiersVisitor visitor(context_, collection, level); + context_.Apply(visitor, query, level, 0 /* since */, 100 /* limit */); + + return true; + } + else + { + return false; + } + } + + virtual bool GetFileContent(MimeType& mime, + std::string& content, + boost::posix_time::ptime& modificationTime, + const UriComponents& path) ORTHANC_OVERRIDE + { + if (path.size() == 4 && + path[0] == DICOM_IDENTIFIERS && + boost::ends_with(path[3], ".dcm")) + { + std::string sopInstanceUid = path[3]; + sopInstanceUid.resize(sopInstanceUid.size() - 4); + + mime = MimeType_Dicom; + + DatabaseLookup query; + query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], + true /* case sensitive */, true /* mandatory tag */); + query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], + true /* case sensitive */, true /* mandatory tag */); + query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, + true /* case sensitive */, true /* mandatory tag */); + + DicomFileVisitor visitor(context_, content); + context_.Apply(visitor, query, ResourceType_Instance, 0 /* since */, 100 /* limit */); + + return visitor.IsSuccess(); + } + else + { + return false; + } + } + + + virtual bool StoreFile(const std::string& content, + const UriComponents& path) ORTHANC_OVERRIDE + { + return false; + } + + + virtual bool CreateFolder(const UriComponents& path) + { + return false; + } + + virtual void Start() ORTHANC_OVERRIDE + { + } + + virtual void Stop() ORTHANC_OVERRIDE + { + } +}; + + + static void PrintHelp(const char* path) { std::cout @@ -1210,7 +1463,8 @@ root.push_back("a"); root.push_back("b"); //httpServer.Register(root, new WebDavStorage(true)); - httpServer.Register(root, new DummyBucket(context, true)); + //httpServer.Register(root, new DummyBucket(context, true)); + httpServer.Register(root, new DummyBucket2(context)); } if (httpServer.GetPortNumber() < 1024)