Orthanc Plugin SDK
Documentation of the plugin interface of Orthanc
OrthancCppDatabasePlugin.h
1 
34 #pragma once
35 
36 #include "OrthancCDatabasePlugin.h"
37 
38 #include <stdexcept>
39 #include <list>
40 #include <string>
41 
42 namespace OrthancPlugins
43 {
44  // This class mimics "boost::noncopyable"
46  {
47  private:
48  NonCopyable(const NonCopyable&);
49 
50  NonCopyable& operator= (const NonCopyable&);
51 
52  protected:
53  NonCopyable()
54  {
55  }
56 
57  ~NonCopyable()
58  {
59  }
60  };
61 
62 
63 
65  {
66  friend class DatabaseBackendAdapter;
67 
68  private:
69  enum AllowedAnswers
70  {
71  AllowedAnswers_All,
72  AllowedAnswers_None,
73  AllowedAnswers_Attachment,
74  AllowedAnswers_Change,
75  AllowedAnswers_DicomTag,
76  AllowedAnswers_ExportedResource
77  };
78 
79  OrthancPluginContext* context_;
80  OrthancPluginDatabaseContext* database_;
81  AllowedAnswers allowedAnswers_;
82 
83  void SetAllowedAnswers(AllowedAnswers allowed)
84  {
85  allowedAnswers_ = allowed;
86  }
87 
88  public:
90  OrthancPluginDatabaseContext* database) :
91  context_(context),
92  database_(database),
93  allowedAnswers_(AllowedAnswers_All /* for unit tests */)
94  {
95  }
96 
97  void LogError(const std::string& message)
98  {
99  OrthancPluginLogError(context_, message.c_str());
100  }
101 
102  void LogWarning(const std::string& message)
103  {
104  OrthancPluginLogWarning(context_, message.c_str());
105  }
106 
107  void LogInfo(const std::string& message)
108  {
109  OrthancPluginLogInfo(context_, message.c_str());
110  }
111 
112  void SignalDeletedAttachment(const std::string& uuid,
113  int32_t contentType,
114  uint64_t uncompressedSize,
115  const std::string& uncompressedHash,
116  int32_t compressionType,
117  uint64_t compressedSize,
118  const std::string& compressedHash)
119  {
120  OrthancPluginAttachment attachment;
121  attachment.uuid = uuid.c_str();
122  attachment.contentType = contentType;
123  attachment.uncompressedSize = uncompressedSize;
124  attachment.uncompressedHash = uncompressedHash.c_str();
125  attachment.compressionType = compressionType;
126  attachment.compressedSize = compressedSize;
127  attachment.compressedHash = compressedHash.c_str();
128 
129  OrthancPluginDatabaseSignalDeletedAttachment(context_, database_, &attachment);
130  }
131 
132  void SignalDeletedResource(const std::string& publicId,
133  OrthancPluginResourceType resourceType)
134  {
135  OrthancPluginDatabaseSignalDeletedResource(context_, database_, publicId.c_str(), resourceType);
136  }
137 
138  void SignalRemainingAncestor(const std::string& ancestorId,
139  OrthancPluginResourceType ancestorType)
140  {
141  OrthancPluginDatabaseSignalRemainingAncestor(context_, database_, ancestorId.c_str(), ancestorType);
142  }
143 
144  void AnswerAttachment(const std::string& uuid,
145  int32_t contentType,
146  uint64_t uncompressedSize,
147  const std::string& uncompressedHash,
148  int32_t compressionType,
149  uint64_t compressedSize,
150  const std::string& compressedHash)
151  {
152  if (allowedAnswers_ != AllowedAnswers_All &&
153  allowedAnswers_ != AllowedAnswers_Attachment)
154  {
155  throw std::runtime_error("Cannot answer with an attachment in the current state");
156  }
157 
158  OrthancPluginAttachment attachment;
159  attachment.uuid = uuid.c_str();
160  attachment.contentType = contentType;
161  attachment.uncompressedSize = uncompressedSize;
162  attachment.uncompressedHash = uncompressedHash.c_str();
163  attachment.compressionType = compressionType;
164  attachment.compressedSize = compressedSize;
165  attachment.compressedHash = compressedHash.c_str();
166 
167  OrthancPluginDatabaseAnswerAttachment(context_, database_, &attachment);
168  }
169 
170  void AnswerChange(int64_t seq,
171  int32_t changeType,
172  OrthancPluginResourceType resourceType,
173  const std::string& publicId,
174  const std::string& date)
175  {
176  if (allowedAnswers_ != AllowedAnswers_All &&
177  allowedAnswers_ != AllowedAnswers_Change)
178  {
179  throw std::runtime_error("Cannot answer with a change in the current state");
180  }
181 
182  OrthancPluginChange change;
183  change.seq = seq;
184  change.changeType = changeType;
185  change.resourceType = resourceType;
186  change.publicId = publicId.c_str();
187  change.date = date.c_str();
188 
189  OrthancPluginDatabaseAnswerChange(context_, database_, &change);
190  }
191 
192  void AnswerDicomTag(uint16_t group,
193  uint16_t element,
194  const std::string& value)
195  {
196  if (allowedAnswers_ != AllowedAnswers_All &&
197  allowedAnswers_ != AllowedAnswers_DicomTag)
198  {
199  throw std::runtime_error("Cannot answer with a DICOM tag in the current state");
200  }
201 
203  tag.group = group;
204  tag.element = element;
205  tag.value = value.c_str();
206 
207  OrthancPluginDatabaseAnswerDicomTag(context_, database_, &tag);
208  }
209 
210  void AnswerExportedResource(int64_t seq,
211  OrthancPluginResourceType resourceType,
212  const std::string& publicId,
213  const std::string& modality,
214  const std::string& date,
215  const std::string& patientId,
216  const std::string& studyInstanceUid,
217  const std::string& seriesInstanceUid,
218  const std::string& sopInstanceUid)
219  {
220  if (allowedAnswers_ != AllowedAnswers_All &&
221  allowedAnswers_ != AllowedAnswers_ExportedResource)
222  {
223  throw std::runtime_error("Cannot answer with an exported resource in the current state");
224  }
225 
227  exported.seq = seq;
228  exported.resourceType = resourceType;
229  exported.publicId = publicId.c_str();
230  exported.modality = modality.c_str();
231  exported.date = date.c_str();
232  exported.patientId = patientId.c_str();
233  exported.studyInstanceUid = studyInstanceUid.c_str();
234  exported.seriesInstanceUid = seriesInstanceUid.c_str();
235  exported.sopInstanceUid = sopInstanceUid.c_str();
236 
237  OrthancPluginDatabaseAnswerExportedResource(context_, database_, &exported);
238  }
239  };
240 
241 
242 
244  {
245  friend class DatabaseBackendAdapter;
246 
247  private:
248  DatabaseBackendOutput* output_;
249 
250  void Finalize()
251  {
252  if (output_ != NULL)
253  {
254  delete output_;
255  output_ = NULL;
256  }
257  }
258 
259  protected:
260  DatabaseBackendOutput& GetOutput()
261  {
262  return *output_;
263  }
264 
265  public:
266  IDatabaseBackend() : output_(NULL)
267  {
268  }
269 
270  virtual ~IDatabaseBackend()
271  {
272  Finalize();
273  }
274 
275  // This takes the ownership
276  void RegisterOutput(DatabaseBackendOutput* output)
277  {
278  Finalize();
279  output_ = output;
280  }
281 
282  virtual void Open() = 0;
283 
284  virtual void Close() = 0;
285 
286  virtual void AddAttachment(int64_t id,
287  const OrthancPluginAttachment& attachment) = 0;
288 
289  virtual void AttachChild(int64_t parent,
290  int64_t child) = 0;
291 
292  virtual void ClearChanges() = 0;
293 
294  virtual void ClearExportedResources() = 0;
295 
296  virtual int64_t CreateResource(const char* publicId,
297  OrthancPluginResourceType type) = 0;
298 
299  virtual void DeleteAttachment(int64_t id,
300  int32_t attachment) = 0;
301 
302  virtual void DeleteMetadata(int64_t id,
303  int32_t metadataType) = 0;
304 
305  virtual void DeleteResource(int64_t id) = 0;
306 
307  virtual void GetAllPublicIds(std::list<std::string>& target,
308  OrthancPluginResourceType resourceType) = 0;
309 
310  /* Use GetOutput().AnswerChange() */
311  virtual void GetChanges(bool& done /*out*/,
312  int64_t since,
313  uint32_t maxResults) = 0;
314 
315  virtual void GetChildrenInternalId(std::list<int64_t>& target /*out*/,
316  int64_t id) = 0;
317 
318  virtual void GetChildrenPublicId(std::list<std::string>& target /*out*/,
319  int64_t id) = 0;
320 
321  /* Use GetOutput().AnswerExportedResource() */
322  virtual void GetExportedResources(bool& done /*out*/,
323  int64_t since,
324  uint32_t maxResults) = 0;
325 
326  /* Use GetOutput().AnswerChange() */
327  virtual void GetLastChange() = 0;
328 
329  /* Use GetOutput().AnswerExportedResource() */
330  virtual void GetLastExportedResource() = 0;
331 
332  /* Use GetOutput().AnswerDicomTag() */
333  virtual void GetMainDicomTags(int64_t id) = 0;
334 
335  virtual std::string GetPublicId(int64_t resourceId) = 0;
336 
337  virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType) = 0;
338 
339  virtual OrthancPluginResourceType GetResourceType(int64_t resourceId) = 0;
340 
341  virtual uint64_t GetTotalCompressedSize() = 0;
342 
343  virtual uint64_t GetTotalUncompressedSize() = 0;
344 
345  virtual bool IsExistingResource(int64_t internalId) = 0;
346 
347  virtual bool IsProtectedPatient(int64_t internalId) = 0;
348 
349  virtual void ListAvailableMetadata(std::list<int32_t>& target /*out*/,
350  int64_t id) = 0;
351 
352  virtual void ListAvailableAttachments(std::list<int32_t>& target /*out*/,
353  int64_t id) = 0;
354 
355  virtual void LogChange(const OrthancPluginChange& change) = 0;
356 
357  virtual void LogExportedResource(const OrthancPluginExportedResource& resource) = 0;
358 
359  /* Use GetOutput().AnswerAttachment() */
360  virtual bool LookupAttachment(int64_t id,
361  int32_t contentType) = 0;
362 
363  virtual bool LookupGlobalProperty(std::string& target /*out*/,
364  int32_t property) = 0;
365 
372  virtual void LookupIdentifier(std::list<int64_t>& target /*out*/,
373  uint16_t group,
374  uint16_t element,
375  const char* value) = 0;
376 
377  virtual void LookupIdentifier(std::list<int64_t>& target /*out*/,
378  const char* value) = 0;
379 
380  virtual bool LookupMetadata(std::string& target /*out*/,
381  int64_t id,
382  int32_t metadataType) = 0;
383 
384  virtual bool LookupParent(int64_t& parentId /*out*/,
385  int64_t resourceId) = 0;
386 
387  virtual bool LookupResource(int64_t& id /*out*/,
388  OrthancPluginResourceType& type /*out*/,
389  const char* publicId) = 0;
390 
391  virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/) = 0;
392 
393  virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/,
394  int64_t patientIdToAvoid) = 0;
395 
396  virtual void SetGlobalProperty(int32_t property,
397  const char* value) = 0;
398 
399  virtual void SetMainDicomTag(int64_t id,
400  uint16_t group,
401  uint16_t element,
402  const char* value) = 0;
403 
404  virtual void SetIdentifierTag(int64_t id,
405  uint16_t group,
406  uint16_t element,
407  const char* value) = 0;
408 
409  virtual void SetMetadata(int64_t id,
410  int32_t metadataType,
411  const char* value) = 0;
412 
413  virtual void SetProtectedPatient(int64_t internalId,
414  bool isProtected) = 0;
415 
416  virtual void StartTransaction() = 0;
417 
418  virtual void RollbackTransaction() = 0;
419 
420  virtual void CommitTransaction() = 0;
421  };
422 
423 
424 
426  {
427  private:
428  // This class cannot be instantiated
430  {
431  }
432 
433  static void LogError(IDatabaseBackend* backend,
434  const std::runtime_error& e)
435  {
436  backend->GetOutput().LogError("Exception in database back-end: " + std::string(e.what()));
437  }
438 
439 
440  static int32_t AddAttachment(void* payload,
441  int64_t id,
442  const OrthancPluginAttachment* attachment)
443  {
444  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
445  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
446 
447  try
448  {
449  backend->AddAttachment(id, *attachment);
450  return 0;
451  }
452  catch (std::runtime_error& e)
453  {
454  LogError(backend, e);
455  return -1;
456  }
457  }
458 
459 
460  static int32_t AttachChild(void* payload,
461  int64_t parent,
462  int64_t child)
463  {
464  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
465  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
466 
467  try
468  {
469  backend->AttachChild(parent, child);
470  return 0;
471  }
472  catch (std::runtime_error& e)
473  {
474  LogError(backend, e);
475  return -1;
476  }
477  }
478 
479 
480  static int32_t ClearChanges(void* payload)
481  {
482  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
483  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
484 
485  try
486  {
487  backend->ClearChanges();
488  return 0;
489  }
490  catch (std::runtime_error& e)
491  {
492  LogError(backend, e);
493  return -1;
494  }
495  }
496 
497 
498  static int32_t ClearExportedResources(void* payload)
499  {
500  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
501  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
502 
503  try
504  {
505  backend->ClearExportedResources();
506  return 0;
507  }
508  catch (std::runtime_error& e)
509  {
510  LogError(backend, e);
511  return -1;
512  }
513  }
514 
515 
516  static int32_t CreateResource(int64_t* id,
517  void* payload,
518  const char* publicId,
519  OrthancPluginResourceType resourceType)
520  {
521  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
522  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
523 
524  try
525  {
526  *id = backend->CreateResource(publicId, resourceType);
527  return 0;
528  }
529  catch (std::runtime_error& e)
530  {
531  LogError(backend, e);
532  return -1;
533  }
534  }
535 
536 
537  static int32_t DeleteAttachment(void* payload,
538  int64_t id,
539  int32_t contentType)
540  {
541  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
542  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
543 
544  try
545  {
546  backend->DeleteAttachment(id, contentType);
547  return 0;
548  }
549  catch (std::runtime_error& e)
550  {
551  LogError(backend, e);
552  return -1;
553  }
554  }
555 
556 
557  static int32_t DeleteMetadata(void* payload,
558  int64_t id,
559  int32_t metadataType)
560  {
561  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
562  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
563 
564  try
565  {
566  backend->DeleteMetadata(id, metadataType);
567  return 0;
568  }
569  catch (std::runtime_error& e)
570  {
571  LogError(backend, e);
572  return -1;
573  }
574  }
575 
576 
577  static int32_t DeleteResource(void* payload,
578  int64_t id)
579  {
580  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
581  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
582 
583  try
584  {
585  backend->DeleteResource(id);
586  return 0;
587  }
588  catch (std::runtime_error& e)
589  {
590  LogError(backend, e);
591  return -1;
592  }
593  }
594 
595 
596  static int32_t GetAllPublicIds(OrthancPluginDatabaseContext* context,
597  void* payload,
598  OrthancPluginResourceType resourceType)
599  {
600  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
601  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
602 
603  try
604  {
605  std::list<std::string> ids;
606  backend->GetAllPublicIds(ids, resourceType);
607 
608  for (std::list<std::string>::const_iterator
609  it = ids.begin(); it != ids.end(); ++it)
610  {
611  OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
612  backend->GetOutput().database_,
613  it->c_str());
614  }
615 
616  return 0;
617  }
618  catch (std::runtime_error& e)
619  {
620  LogError(backend, e);
621  return -1;
622  }
623  }
624 
625 
626  static int32_t GetChanges(OrthancPluginDatabaseContext* context,
627  void* payload,
628  int64_t since,
629  uint32_t maxResult)
630  {
631  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
632  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change);
633 
634  try
635  {
636  bool done;
637  backend->GetChanges(done, since, maxResult);
638 
639  if (done)
640  {
641  OrthancPluginDatabaseAnswerChangesDone(backend->GetOutput().context_,
642  backend->GetOutput().database_);
643  }
644 
645  return 0;
646  }
647  catch (std::runtime_error& e)
648  {
649  LogError(backend, e);
650  return -1;
651  }
652  }
653 
654 
655  static int32_t GetChildrenInternalId(OrthancPluginDatabaseContext* context,
656  void* payload,
657  int64_t id)
658  {
659  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
660  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
661 
662  try
663  {
664  std::list<int64_t> target;
665  backend->GetChildrenInternalId(target, id);
666 
667  for (std::list<int64_t>::const_iterator
668  it = target.begin(); it != target.end(); ++it)
669  {
670  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
671  backend->GetOutput().database_, *it);
672  }
673 
674  return 0;
675  }
676  catch (std::runtime_error& e)
677  {
678  LogError(backend, e);
679  return -1;
680  }
681  }
682 
683 
684  static int32_t GetChildrenPublicId(OrthancPluginDatabaseContext* context,
685  void* payload,
686  int64_t id)
687  {
688  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
689  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
690 
691  try
692  {
693  std::list<std::string> ids;
694  backend->GetChildrenPublicId(ids, id);
695 
696  for (std::list<std::string>::const_iterator
697  it = ids.begin(); it != ids.end(); ++it)
698  {
699  OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
700  backend->GetOutput().database_,
701  it->c_str());
702  }
703 
704  return 0;
705  }
706  catch (std::runtime_error& e)
707  {
708  LogError(backend, e);
709  return -1;
710  }
711  }
712 
713 
714  static int32_t GetExportedResources(OrthancPluginDatabaseContext* context,
715  void* payload,
716  int64_t since,
717  uint32_t maxResult)
718  {
719  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
720  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource);
721 
722  try
723  {
724  bool done;
725  backend->GetExportedResources(done, since, maxResult);
726 
727  if (done)
728  {
729  OrthancPluginDatabaseAnswerExportedResourcesDone(backend->GetOutput().context_,
730  backend->GetOutput().database_);
731  }
732  return 0;
733  }
734  catch (std::runtime_error& e)
735  {
736  LogError(backend, e);
737  return -1;
738  }
739  }
740 
741 
742  static int32_t GetLastChange(OrthancPluginDatabaseContext* context,
743  void* payload)
744  {
745  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
746  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change);
747 
748  try
749  {
750  backend->GetLastChange();
751  return 0;
752  }
753  catch (std::runtime_error& e)
754  {
755  LogError(backend, e);
756  return -1;
757  }
758  }
759 
760 
761  static int32_t GetLastExportedResource(OrthancPluginDatabaseContext* context,
762  void* payload)
763  {
764  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
765  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource);
766 
767  try
768  {
769  backend->GetLastExportedResource();
770  return 0;
771  }
772  catch (std::runtime_error& e)
773  {
774  LogError(backend, e);
775  return -1;
776  }
777  }
778 
779 
780  static int32_t GetMainDicomTags(OrthancPluginDatabaseContext* context,
781  void* payload,
782  int64_t id)
783  {
784  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
785  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_DicomTag);
786 
787  try
788  {
789  backend->GetMainDicomTags(id);
790  return 0;
791  }
792  catch (std::runtime_error& e)
793  {
794  LogError(backend, e);
795  return -1;
796  }
797  }
798 
799 
800  static int32_t GetPublicId(OrthancPluginDatabaseContext* context,
801  void* payload,
802  int64_t id)
803  {
804  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
805  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
806 
807  try
808  {
809  std::string s = backend->GetPublicId(id);
810  OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
811  backend->GetOutput().database_,
812  s.c_str());
813 
814  return 0;
815  }
816  catch (std::runtime_error& e)
817  {
818  LogError(backend, e);
819  return -1;
820  }
821  }
822 
823 
824  static int32_t GetResourceCount(uint64_t* target,
825  void* payload,
826  OrthancPluginResourceType resourceType)
827  {
828  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
829  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
830 
831  try
832  {
833  *target = backend->GetResourceCount(resourceType);
834  return 0;
835  }
836  catch (std::runtime_error& e)
837  {
838  LogError(backend, e);
839  return -1;
840  }
841  }
842 
843 
844  static int32_t GetResourceType(OrthancPluginResourceType* resourceType,
845  void* payload,
846  int64_t id)
847  {
848  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
849  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
850 
851  try
852  {
853  *resourceType = backend->GetResourceType(id);
854  return 0;
855  }
856  catch (std::runtime_error& e)
857  {
858  LogError(backend, e);
859  return -1;
860  }
861  }
862 
863 
864  static int32_t GetTotalCompressedSize(uint64_t* target,
865  void* payload)
866  {
867  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
868  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
869 
870  try
871  {
872  *target = backend->GetTotalCompressedSize();
873  return 0;
874  }
875  catch (std::runtime_error& e)
876  {
877  LogError(backend, e);
878  return -1;
879  }
880  }
881 
882 
883  static int32_t GetTotalUncompressedSize(uint64_t* target,
884  void* payload)
885  {
886  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
887  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
888 
889  try
890  {
891  *target = backend->GetTotalUncompressedSize();
892  return 0;
893  }
894  catch (std::runtime_error& e)
895  {
896  LogError(backend, e);
897  return -1;
898  }
899  }
900 
901 
902  static int32_t IsExistingResource(int32_t* existing,
903  void* payload,
904  int64_t id)
905  {
906  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
907  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
908 
909  try
910  {
911  *existing = backend->IsExistingResource(id);
912  return 0;
913  }
914  catch (std::runtime_error& e)
915  {
916  LogError(backend, e);
917  return -1;
918  }
919  }
920 
921 
922  static int32_t IsProtectedPatient(int32_t* isProtected,
923  void* payload,
924  int64_t id)
925  {
926  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
927  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
928 
929  try
930  {
931  *isProtected = backend->IsProtectedPatient(id);
932  return 0;
933  }
934  catch (std::runtime_error& e)
935  {
936  LogError(backend, e);
937  return -1;
938  }
939  }
940 
941 
942  static int32_t ListAvailableMetadata(OrthancPluginDatabaseContext* context,
943  void* payload,
944  int64_t id)
945  {
946  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
947  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
948 
949  try
950  {
951  std::list<int32_t> target;
952  backend->ListAvailableMetadata(target, id);
953 
954  for (std::list<int32_t>::const_iterator
955  it = target.begin(); it != target.end(); ++it)
956  {
957  OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_,
958  backend->GetOutput().database_,
959  *it);
960  }
961 
962  return 0;
963  }
964  catch (std::runtime_error& e)
965  {
966  LogError(backend, e);
967  return -1;
968  }
969  }
970 
971 
972  static int32_t ListAvailableAttachments(OrthancPluginDatabaseContext* context,
973  void* payload,
974  int64_t id)
975  {
976  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
977  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
978 
979  try
980  {
981  std::list<int32_t> target;
982  backend->ListAvailableAttachments(target, id);
983 
984  for (std::list<int32_t>::const_iterator
985  it = target.begin(); it != target.end(); ++it)
986  {
987  OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_,
988  backend->GetOutput().database_,
989  *it);
990  }
991 
992  return 0;
993  }
994  catch (std::runtime_error& e)
995  {
996  LogError(backend, e);
997  return -1;
998  }
999  }
1000 
1001 
1002  static int32_t LogChange(void* payload,
1003  const OrthancPluginChange* change)
1004  {
1005  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1006  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1007 
1008  try
1009  {
1010  backend->LogChange(*change);
1011  return 0;
1012  }
1013  catch (std::runtime_error& e)
1014  {
1015  LogError(backend, e);
1016  return -1;
1017  }
1018  }
1019 
1020 
1021  static int32_t LogExportedResource(void* payload,
1022  const OrthancPluginExportedResource* exported)
1023  {
1024  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1025  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1026 
1027  try
1028  {
1029  backend->LogExportedResource(*exported);
1030  return 0;
1031  }
1032  catch (std::runtime_error& e)
1033  {
1034  LogError(backend, e);
1035  return -1;
1036  }
1037  }
1038 
1039 
1040  static int32_t LookupAttachment(OrthancPluginDatabaseContext* context,
1041  void* payload,
1042  int64_t id,
1043  int32_t contentType)
1044  {
1045  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1046  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Attachment);
1047 
1048  try
1049  {
1050  backend->LookupAttachment(id, contentType);
1051  return 0;
1052  }
1053  catch (std::runtime_error& e)
1054  {
1055  LogError(backend, e);
1056  return -1;
1057  }
1058  }
1059 
1060 
1061  static int32_t LookupGlobalProperty(OrthancPluginDatabaseContext* context,
1062  void* payload,
1063  int32_t property)
1064  {
1065  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1066  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1067 
1068  try
1069  {
1070  std::string s;
1071  if (backend->LookupGlobalProperty(s, property))
1072  {
1073  OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
1074  backend->GetOutput().database_,
1075  s.c_str());
1076  }
1077 
1078  return 0;
1079  }
1080  catch (std::runtime_error& e)
1081  {
1082  LogError(backend, e);
1083  return -1;
1084  }
1085  }
1086 
1087 
1088  static int32_t LookupIdentifier(OrthancPluginDatabaseContext* context,
1089  void* payload,
1090  const OrthancPluginDicomTag* tag)
1091  {
1092  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1093  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1094 
1095  try
1096  {
1097  std::list<int64_t> target;
1098  backend->LookupIdentifier(target, tag->group, tag->element, tag->value);
1099 
1100  for (std::list<int64_t>::const_iterator
1101  it = target.begin(); it != target.end(); ++it)
1102  {
1103  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
1104  backend->GetOutput().database_, *it);
1105  }
1106 
1107  return 0;
1108  }
1109  catch (std::runtime_error& e)
1110  {
1111  LogError(backend, e);
1112  return -1;
1113  }
1114  }
1115 
1116 
1117  static int32_t LookupIdentifier2(OrthancPluginDatabaseContext* context,
1118  void* payload,
1119  const char* value)
1120  {
1121  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1122  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1123 
1124  try
1125  {
1126  std::list<int64_t> target;
1127  backend->LookupIdentifier(target, value);
1128 
1129  for (std::list<int64_t>::const_iterator
1130  it = target.begin(); it != target.end(); ++it)
1131  {
1132  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
1133  backend->GetOutput().database_, *it);
1134  }
1135 
1136  return 0;
1137  }
1138  catch (std::runtime_error& e)
1139  {
1140  LogError(backend, e);
1141  return -1;
1142  }
1143  }
1144 
1145 
1146  static int32_t LookupMetadata(OrthancPluginDatabaseContext* context,
1147  void* payload,
1148  int64_t id,
1149  int32_t metadata)
1150  {
1151  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1152  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1153 
1154  try
1155  {
1156  std::string s;
1157  if (backend->LookupMetadata(s, id, metadata))
1158  {
1159  OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
1160  backend->GetOutput().database_, s.c_str());
1161  }
1162 
1163  return 0;
1164  }
1165  catch (std::runtime_error& e)
1166  {
1167  LogError(backend, e);
1168  return -1;
1169  }
1170  }
1171 
1172 
1173  static int32_t LookupParent(OrthancPluginDatabaseContext* context,
1174  void* payload,
1175  int64_t id)
1176  {
1177  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1178  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1179 
1180  try
1181  {
1182  int64_t parent;
1183  if (backend->LookupParent(parent, id))
1184  {
1185  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
1186  backend->GetOutput().database_, parent);
1187  }
1188 
1189  return 0;
1190  }
1191  catch (std::runtime_error& e)
1192  {
1193  LogError(backend, e);
1194  return -1;
1195  }
1196  }
1197 
1198 
1199  static int32_t LookupResource(OrthancPluginDatabaseContext* context,
1200  void* payload,
1201  const char* publicId)
1202  {
1203  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1204  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1205 
1206  try
1207  {
1208  int64_t id;
1210  if (backend->LookupResource(id, type, publicId))
1211  {
1212  OrthancPluginDatabaseAnswerResource(backend->GetOutput().context_,
1213  backend->GetOutput().database_,
1214  id, type);
1215  }
1216 
1217  return 0;
1218  }
1219  catch (std::runtime_error& e)
1220  {
1221  LogError(backend, e);
1222  return -1;
1223  }
1224  }
1225 
1226 
1227  static int32_t SelectPatientToRecycle(OrthancPluginDatabaseContext* context,
1228  void* payload)
1229  {
1230  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1231  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1232 
1233  try
1234  {
1235  int64_t id;
1236  if (backend->SelectPatientToRecycle(id))
1237  {
1238  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
1239  backend->GetOutput().database_, id);
1240  }
1241 
1242  return 0;
1243  }
1244  catch (std::runtime_error& e)
1245  {
1246  LogError(backend, e);
1247  return -1;
1248  }
1249  }
1250 
1251 
1252  static int32_t SelectPatientToRecycle2(OrthancPluginDatabaseContext* context,
1253  void* payload,
1254  int64_t patientIdToAvoid)
1255  {
1256  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1257  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1258 
1259  try
1260  {
1261  int64_t id;
1262  if (backend->SelectPatientToRecycle(id, patientIdToAvoid))
1263  {
1264  OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_,
1265  backend->GetOutput().database_, id);
1266  }
1267 
1268  return 0;
1269  }
1270  catch (std::runtime_error& e)
1271  {
1272  LogError(backend, e);
1273  return -1;
1274  }
1275  }
1276 
1277 
1278  static int32_t SetGlobalProperty(void* payload,
1279  int32_t property,
1280  const char* value)
1281  {
1282  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1283  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1284 
1285  try
1286  {
1287  backend->SetGlobalProperty(property, value);
1288  return 0;
1289  }
1290  catch (std::runtime_error& e)
1291  {
1292  LogError(backend, e);
1293  return -1;
1294  }
1295  }
1296 
1297 
1298  static int32_t SetMainDicomTag(void* payload,
1299  int64_t id,
1300  const OrthancPluginDicomTag* tag)
1301  {
1302  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1303  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1304 
1305  try
1306  {
1307  backend->SetMainDicomTag(id, tag->group, tag->element, tag->value);
1308  return 0;
1309  }
1310  catch (std::runtime_error& e)
1311  {
1312  LogError(backend, e);
1313  return -1;
1314  }
1315  }
1316 
1317 
1318  static int32_t SetIdentifierTag(void* payload,
1319  int64_t id,
1320  const OrthancPluginDicomTag* tag)
1321  {
1322  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1323  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1324 
1325  try
1326  {
1327  backend->SetIdentifierTag(id, tag->group, tag->element, tag->value);
1328  return 0;
1329  }
1330  catch (std::runtime_error& e)
1331  {
1332  LogError(backend, e);
1333  return -1;
1334  }
1335  }
1336 
1337 
1338  static int32_t SetMetadata(void* payload,
1339  int64_t id,
1340  int32_t metadata,
1341  const char* value)
1342  {
1343  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1344  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1345 
1346  try
1347  {
1348  backend->SetMetadata(id, metadata, value);
1349  return 0;
1350  }
1351  catch (std::runtime_error& e)
1352  {
1353  LogError(backend, e);
1354  return -1;
1355  }
1356  }
1357 
1358 
1359  static int32_t SetProtectedPatient(void* payload,
1360  int64_t id,
1361  int32_t isProtected)
1362  {
1363  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1364  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1365 
1366  try
1367  {
1368  backend->SetProtectedPatient(id, isProtected);
1369  return 0;
1370  }
1371  catch (std::runtime_error& e)
1372  {
1373  LogError(backend, e);
1374  return -1;
1375  }
1376  }
1377 
1378 
1379  static int32_t StartTransaction(void* payload)
1380  {
1381  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1382  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1383 
1384  try
1385  {
1386  backend->StartTransaction();
1387  return 0;
1388  }
1389  catch (std::runtime_error& e)
1390  {
1391  LogError(backend, e);
1392  return -1;
1393  }
1394  }
1395 
1396 
1397  static int32_t RollbackTransaction(void* payload)
1398  {
1399  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1400  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1401 
1402  try
1403  {
1404  backend->RollbackTransaction();
1405  return 0;
1406  }
1407  catch (std::runtime_error& e)
1408  {
1409  LogError(backend, e);
1410  return -1;
1411  }
1412  }
1413 
1414 
1415  static int32_t CommitTransaction(void* payload)
1416  {
1417  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1418  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1419 
1420  try
1421  {
1422  backend->CommitTransaction();
1423  return 0;
1424  }
1425  catch (std::runtime_error& e)
1426  {
1427  LogError(backend, e);
1428  return -1;
1429  }
1430  }
1431 
1432 
1433  static int32_t Open(void* payload)
1434  {
1435  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1436  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1437 
1438  try
1439  {
1440  backend->Open();
1441  return 0;
1442  }
1443  catch (std::runtime_error& e)
1444  {
1445  LogError(backend, e);
1446  return -1;
1447  }
1448  }
1449 
1450 
1451  static int32_t Close(void* payload)
1452  {
1453  IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
1454  backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
1455 
1456  try
1457  {
1458  backend->Close();
1459  return 0;
1460  }
1461  catch (std::runtime_error& e)
1462  {
1463  LogError(backend, e);
1464  return -1;
1465  }
1466  }
1467 
1468 
1469  public:
1470  static void Register(OrthancPluginContext* context,
1471  IDatabaseBackend& backend)
1472  {
1474  memset(&params, 0, sizeof(params));
1475 
1476  params.addAttachment = AddAttachment;
1477  params.attachChild = AttachChild;
1478  params.clearChanges = ClearChanges;
1479  params.clearExportedResources = ClearExportedResources;
1480  params.createResource = CreateResource;
1481  params.deleteAttachment = DeleteAttachment;
1482  params.deleteMetadata = DeleteMetadata;
1483  params.deleteResource = DeleteResource;
1484  params.getAllPublicIds = GetAllPublicIds;
1485  params.getChanges = GetChanges;
1486  params.getChildrenInternalId = GetChildrenInternalId;
1487  params.getChildrenPublicId = GetChildrenPublicId;
1488  params.getExportedResources = GetExportedResources;
1489  params.getLastChange = GetLastChange;
1490  params.getLastExportedResource = GetLastExportedResource;
1491  params.getMainDicomTags = GetMainDicomTags;
1492  params.getPublicId = GetPublicId;
1493  params.getResourceCount = GetResourceCount;
1494  params.getResourceType = GetResourceType;
1495  params.getTotalCompressedSize = GetTotalCompressedSize;
1496  params.getTotalUncompressedSize = GetTotalUncompressedSize;
1497  params.isExistingResource = IsExistingResource;
1498  params.isProtectedPatient = IsProtectedPatient;
1499  params.listAvailableMetadata = ListAvailableMetadata;
1500  params.listAvailableAttachments = ListAvailableAttachments;
1501  params.logChange = LogChange;
1502  params.logExportedResource = LogExportedResource;
1503  params.lookupAttachment = LookupAttachment;
1504  params.lookupGlobalProperty = LookupGlobalProperty;
1505  params.lookupIdentifier = LookupIdentifier;
1506  params.lookupIdentifier2 = LookupIdentifier2;
1507  params.lookupMetadata = LookupMetadata;
1508  params.lookupParent = LookupParent;
1509  params.lookupResource = LookupResource;
1510  params.selectPatientToRecycle = SelectPatientToRecycle;
1511  params.selectPatientToRecycle2 = SelectPatientToRecycle2;
1512  params.setGlobalProperty = SetGlobalProperty;
1513  params.setMainDicomTag = SetMainDicomTag;
1514  params.setIdentifierTag = SetIdentifierTag;
1515  params.setMetadata = SetMetadata;
1516  params.setProtectedPatient = SetProtectedPatient;
1517  params.startTransaction = StartTransaction;
1518  params.rollbackTransaction = RollbackTransaction;
1519  params.commitTransaction = CommitTransaction;
1520  params.open = Open;
1521  params.close = Close;
1522 
1523  OrthancPluginDatabaseContext* database = OrthancPluginRegisterDatabaseBackend(context, &params, &backend);
1524  if (!context)
1525  {
1526  throw std::runtime_error("Unable to register the database backend");
1527  }
1528 
1529  backend.RegisterOutput(new DatabaseBackendOutput(context, database));
1530  }
1531  };
1532 }
Definition: OrthancCDatabasePlugin.h:88
void OrthancPluginLogInfo(OrthancPluginContext *context, const char *message)
Log an information.
Definition: OrthancCPlugin.h:694
void OrthancPluginLogError(OrthancPluginContext *context, const char *message)
Log an error.
Definition: OrthancCPlugin.h:662
OrthancPluginResourceType
Definition: OrthancCPlugin.h:377
virtual void LookupIdentifier(std::list< int64_t > &target, uint16_t group, uint16_t element, const char *value)=0
Definition: OrthancCppDatabasePlugin.h:42
Definition: OrthancCppDatabasePlugin.h:45
Definition: OrthancCDatabasePlugin.h:81
struct _OrthancPluginContext_t OrthancPluginContext
Data structure that contains information about the Orthanc core.
Definition: OrthancCppDatabasePlugin.h:425
Definition: OrthancCppDatabasePlugin.h:64
Definition: OrthancCDatabasePlugin.h:97
Definition: OrthancCDatabasePlugin.h:309
Definition: OrthancCppDatabasePlugin.h:243
Definition: OrthancCDatabasePlugin.h:70
void OrthancPluginLogWarning(OrthancPluginContext *context, const char *message)
Log a warning.
Definition: OrthancCPlugin.h:678