comparison Framework/Plugins/DatabaseBackendAdapterV2.cpp @ 205:873e37048f96

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