# HG changeset patch # User Sebastien Jodogne # Date 1616145077 -3600 # Node ID 6dcf57074dd4006ee88559a253b94b197bdc114f # Parent 873e37048f9682b4810a7f09c61017b79472e1ad starting OrthancPluginDatabaseBackendV3 wrapper diff -r 873e37048f96 -r 6dcf57074dd4 Framework/Plugins/IDatabaseBackendOutput.h --- a/Framework/Plugins/IDatabaseBackendOutput.h Thu Mar 18 18:32:05 2021 +0100 +++ b/Framework/Plugins/IDatabaseBackendOutput.h Fri Mar 19 10:11:17 2021 +0100 @@ -83,6 +83,7 @@ const std::string& studyInstanceUid, const std::string& seriesInstanceUid, const std::string& sopInstanceUid) = 0; + #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void AnswerMatchingResource(const std::string& resourceId) = 0; #endif diff -r 873e37048f96 -r 6dcf57074dd4 SQLite/Plugins/IndexPlugin.cpp --- a/SQLite/Plugins/IndexPlugin.cpp Thu Mar 18 18:32:05 2021 +0100 +++ b/SQLite/Plugins/IndexPlugin.cpp Fri Mar 19 10:11:17 2021 +0100 @@ -28,6 +28,383 @@ static std::unique_ptr backend_; + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 10, 0) + +namespace OrthancDatabases +{ + class Output : public IDatabaseBackendOutput + { + private: + _OrthancPluginDatabaseAnswerType answerType_; + std::list strings_; + + std::vector attachments_; + std::vector changes_; + std::vector tags_; + std::vector exported_; + std::vector events_; + + const char* StoreString(const std::string& s) + { + strings_.push_back(s); + return strings_.back().c_str(); + } + + void SetupAnswerType(_OrthancPluginDatabaseAnswerType type) + { + if (answerType_ == _OrthancPluginDatabaseAnswerType_None) + { + answerType_ = type; + } + else if (answerType_ != type) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + public: + Output() : + answerType_(_OrthancPluginDatabaseAnswerType_None) + { + } + + + void Clear() + { + answerType_ = _OrthancPluginDatabaseAnswerType_None; + strings_.clear(); + + attachments_.clear(); + changes_.clear(); + tags_.clear(); + exported_.clear(); + events_.clear(); + } + + + static OrthancPluginErrorCode ReadAnswersCount(OrthancPluginDatabaseTransaction* transaction, + uint32_t* target /* out */) + { + const Output& that = *reinterpret_cast(transaction); + + size_t size; + + switch (that.answerType_) + { + case _OrthancPluginDatabaseAnswerType_None: + size = 0; + break; + + case _OrthancPluginDatabaseAnswerType_Attachment: + size = that.attachments_.size(); + break; + + case _OrthancPluginDatabaseAnswerType_Change: + size = that.changes_.size(); + break; + + case _OrthancPluginDatabaseAnswerType_DicomTag: + size = that.tags_.size(); + break; + + case _OrthancPluginDatabaseAnswerType_ExportedResource: + size = that.exported_.size(); + break; + + default: + return OrthancPluginErrorCode_InternalError; + } + + *target = static_cast(size); + return OrthancPluginErrorCode_Success; + } + + + static OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginAttachment* target /* out */, + uint32_t index) + { + const Output& that = *reinterpret_cast(transaction); + + if (index < that.attachments_.size()) + { + *target = that.attachments_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + static OrthancPluginErrorCode ReadAnswerChange(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginChange* target /* out */, + uint32_t index) + { + const Output& that = *reinterpret_cast(transaction); + + if (index < that.changes_.size()) + { + *target = that.changes_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + static OrthancPluginErrorCode ReadAnswerDicomTag(OrthancPluginDatabaseTransaction* transaction, + uint16_t* group, + uint16_t* element, + const char** value, + uint32_t index) + { + const Output& that = *reinterpret_cast(transaction); + + if (index < that.tags_.size()) + { + const OrthancPluginDicomTag& tag = that.tags_[index]; + *group = tag.group; + *element = tag.element; + *value = tag.value; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + static OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginExportedResource* target /* out */, + uint32_t index) + { + const Output& that = *reinterpret_cast(transaction); + + if (index < that.exported_.size()) + { + *target = that.exported_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + static OrthancPluginErrorCode ReadEventsCount(OrthancPluginDatabaseTransaction* transaction, + uint32_t* target /* out */) + { + const Output& that = *reinterpret_cast(transaction); + *target = static_cast(that.events_.size()); + return OrthancPluginErrorCode_Success; + } + + + static OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginDatabaseEvent* event /* out */, + uint32_t index) + { + const Output& that = *reinterpret_cast(transaction); + + if (index < that.events_.size()) + { + *event = that.events_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + virtual void SignalDeletedAttachment(const std::string& uuid, + int32_t contentType, + uint64_t uncompressedSize, + const std::string& uncompressedHash, + int32_t compressionType, + uint64_t compressedSize, + const std::string& compressedHash) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_DeletedAttachment; + event.content.attachment.uuid = StoreString(uuid); + event.content.attachment.contentType = contentType; + event.content.attachment.uncompressedSize = uncompressedSize; + event.content.attachment.uncompressedHash = StoreString(uncompressedHash); + event.content.attachment.compressionType = compressionType; + event.content.attachment.compressedSize = compressedSize; + event.content.attachment.compressedHash = StoreString(compressedHash); + + events_.push_back(event); + } + + + virtual void SignalDeletedResource(const std::string& publicId, + OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_DeletedResource; + event.content.resource.level = resourceType; + event.content.resource.publicId = StoreString(publicId); + + events_.push_back(event); + } + + + virtual void SignalRemainingAncestor(const std::string& ancestorId, + OrthancPluginResourceType ancestorType) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_RemainingAncestor; + event.content.resource.level = ancestorType; + event.content.resource.publicId = StoreString(ancestorId); + + events_.push_back(event); + } + + + virtual void AnswerAttachment(const std::string& uuid, + int32_t contentType, + uint64_t uncompressedSize, + const std::string& uncompressedHash, + int32_t compressionType, + uint64_t compressedSize, + const std::string& compressedHash) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Attachment); + + OrthancPluginAttachment attachment; + attachment.uuid = StoreString(uuid); + attachment.contentType = contentType; + attachment.uncompressedSize = uncompressedSize; + attachment.uncompressedHash = StoreString(uncompressedHash); + attachment.compressionType = compressionType; + attachment.compressedSize = compressedSize; + attachment.compressedHash = StoreString(compressedHash); + + attachments_.push_back(attachment); + } + + + virtual void AnswerChange(int64_t seq, + int32_t changeType, + OrthancPluginResourceType resourceType, + const std::string& publicId, + const std::string& date) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Change); + + OrthancPluginChange change; + change.seq = seq; + change.changeType = changeType; + change.resourceType = resourceType; + change.publicId = StoreString(publicId); + change.date = StoreString(date); + + changes_.push_back(change); + } + + + virtual void AnswerDicomTag(uint16_t group, + uint16_t element, + const std::string& value) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_DicomTag); + + OrthancPluginDicomTag tag; + tag.group = group; + tag.element = element; + tag.value = StoreString(value); + + tags_.push_back(tag); + } + + + virtual void AnswerExportedResource(int64_t seq, + OrthancPluginResourceType resourceType, + const std::string& publicId, + const std::string& modality, + const std::string& date, + const std::string& patientId, + const std::string& studyInstanceUid, + const std::string& seriesInstanceUid, + const std::string& sopInstanceUid) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_ExportedResource); + + OrthancPluginExportedResource exported; + exported.seq = seq; + exported.resourceType = resourceType; + exported.publicId = StoreString(publicId); + exported.modality = StoreString(modality); + exported.date = StoreString(date); + exported.patientId = StoreString(patientId); + exported.studyInstanceUid = StoreString(studyInstanceUid); + exported.seriesInstanceUid = StoreString(seriesInstanceUid); + exported.sopInstanceUid = StoreString(sopInstanceUid); + + exported_.push_back(exported); + } + + + virtual void AnswerMatchingResource(const std::string& resourceId) ORTHANC_OVERRIDE + { + + } + + + virtual void AnswerMatchingResource(const std::string& resourceId, + const std::string& someInstanceId) ORTHANC_OVERRIDE + { + + } + }; + + + class Factory : public IDatabaseBackendOutput::IFactory + { + public: + Factory() + { + } + + virtual IDatabaseBackendOutput* CreateOutput() + { + return new Output; + } + }; + + + static void Register() + { + OrthancPluginDatabaseBackendV3 backend; + memset(&backend, 0, sizeof(backend)); + + backend.readAnswersCount = Output::ReadAnswersCount; + backend.readAnswerAttachment = Output::ReadAnswerAttachment; + backend.readAnswerChange = Output::ReadAnswerChange; + backend.readAnswerDicomTag = Output::ReadAnswerDicomTag; + backend.readAnswerExportedResource = Output::ReadAnswerExportedResource; + + backend.readEventsCount = Output::ReadEventsCount; + backend.readEvent = Output::ReadEvent; + } +} + +# endif +#endif + + + extern "C" { ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)