Mercurial > hg > orthanc
comparison Plugins/Engine/OrthancPluginDatabase.cpp @ 1309:8f4487d8f79e db-changes
new files for custom database back-end
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 11 Feb 2015 10:36:22 +0100 |
parents | |
children | 01be1432bda9 |
comparison
equal
deleted
inserted
replaced
1308:f7966e9950e4 | 1309:8f4487d8f79e |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
10 * | |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
22 * | |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
33 #include "OrthancPluginDatabase.h" | |
34 | |
35 #include "../../Core/OrthancException.h" | |
36 | |
37 #include <cassert> | |
38 #include <glog/logging.h> | |
39 | |
40 namespace Orthanc | |
41 { | |
42 static OrthancPluginResourceType Convert(ResourceType type) | |
43 { | |
44 switch (type) | |
45 { | |
46 case ResourceType_Patient: | |
47 return OrthancPluginResourceType_Patient; | |
48 | |
49 case ResourceType_Study: | |
50 return OrthancPluginResourceType_Study; | |
51 | |
52 case ResourceType_Series: | |
53 return OrthancPluginResourceType_Series; | |
54 | |
55 case ResourceType_Instance: | |
56 return OrthancPluginResourceType_Instance; | |
57 | |
58 default: | |
59 throw OrthancException(ErrorCode_InternalError); | |
60 } | |
61 } | |
62 | |
63 | |
64 static ResourceType Convert(OrthancPluginResourceType type) | |
65 { | |
66 switch (type) | |
67 { | |
68 case OrthancPluginResourceType_Patient: | |
69 return ResourceType_Patient; | |
70 | |
71 case OrthancPluginResourceType_Study: | |
72 return ResourceType_Study; | |
73 | |
74 case OrthancPluginResourceType_Series: | |
75 return ResourceType_Series; | |
76 | |
77 case OrthancPluginResourceType_Instance: | |
78 return ResourceType_Instance; | |
79 | |
80 default: | |
81 throw OrthancException(ErrorCode_InternalError); | |
82 } | |
83 } | |
84 | |
85 | |
86 static FileInfo Convert(const OrthancPluginAttachment& attachment) | |
87 { | |
88 return FileInfo(attachment.uuid, | |
89 static_cast<FileContentType>(attachment.contentType), | |
90 attachment.uncompressedSize, | |
91 attachment.uncompressedHash, | |
92 static_cast<CompressionType>(attachment.compressionType), | |
93 attachment.compressedSize, | |
94 attachment.compressedHash); | |
95 } | |
96 | |
97 | |
98 void OrthancPluginDatabase::ResetAnswers() | |
99 { | |
100 type_ = _OrthancPluginDatabaseAnswerType_None; | |
101 | |
102 answerDicomMap_ = NULL; | |
103 answerChanges_ = NULL; | |
104 answerExportedResources_ = NULL; | |
105 answerDone_ = NULL; | |
106 } | |
107 | |
108 | |
109 void OrthancPluginDatabase::ForwardAnswers(std::list<int64_t>& target) | |
110 { | |
111 if (type_ != _OrthancPluginDatabaseAnswerType_None && | |
112 type_ != _OrthancPluginDatabaseAnswerType_Int64) | |
113 { | |
114 throw OrthancException(ErrorCode_Plugin); | |
115 } | |
116 | |
117 target.clear(); | |
118 | |
119 if (type_ == _OrthancPluginDatabaseAnswerType_Int64) | |
120 { | |
121 for (std::list<int64_t>::const_iterator | |
122 it = answerInt64_.begin(); it != answerInt64_.end(); it++) | |
123 { | |
124 target.push_back(*it); | |
125 } | |
126 } | |
127 } | |
128 | |
129 | |
130 void OrthancPluginDatabase::ForwardAnswers(std::list<std::string>& target) | |
131 { | |
132 if (type_ != _OrthancPluginDatabaseAnswerType_None && | |
133 type_ != _OrthancPluginDatabaseAnswerType_String) | |
134 { | |
135 throw OrthancException(ErrorCode_Plugin); | |
136 } | |
137 | |
138 target.clear(); | |
139 | |
140 if (type_ == _OrthancPluginDatabaseAnswerType_String) | |
141 { | |
142 for (std::list<std::string>::const_iterator | |
143 it = answerStrings_.begin(); it != answerStrings_.end(); it++) | |
144 { | |
145 target.push_back(*it); | |
146 } | |
147 } | |
148 } | |
149 | |
150 | |
151 bool OrthancPluginDatabase::ForwardSingleAnswer(std::string& target) | |
152 { | |
153 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
154 { | |
155 return false; | |
156 } | |
157 else if (type_ == _OrthancPluginDatabaseAnswerType_String && | |
158 answerStrings_.size() == 1) | |
159 { | |
160 target = answerStrings_.front(); | |
161 return true; | |
162 } | |
163 else | |
164 { | |
165 throw OrthancException(ErrorCode_Plugin); | |
166 } | |
167 } | |
168 | |
169 | |
170 bool OrthancPluginDatabase::ForwardSingleAnswer(int64_t& target) | |
171 { | |
172 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
173 { | |
174 return false; | |
175 } | |
176 else if (type_ == _OrthancPluginDatabaseAnswerType_Int64 && | |
177 answerInt64_.size() == 1) | |
178 { | |
179 target = answerInt64_.front(); | |
180 return true; | |
181 } | |
182 else | |
183 { | |
184 throw OrthancException(ErrorCode_Plugin); | |
185 } | |
186 } | |
187 | |
188 | |
189 void OrthancPluginDatabase::AddAttachment(int64_t id, | |
190 const FileInfo& attachment) | |
191 { | |
192 OrthancPluginAttachment tmp; | |
193 tmp.uuid = attachment.GetUuid().c_str(); | |
194 tmp.contentType = static_cast<int32_t>(attachment.GetContentType()); | |
195 tmp.uncompressedSize = attachment.GetUncompressedSize(); | |
196 tmp.uncompressedHash = attachment.GetUncompressedMD5().c_str(); | |
197 tmp.compressionType = static_cast<int32_t>(attachment.GetCompressionType()); | |
198 tmp.compressedSize = attachment.GetCompressedSize(); | |
199 tmp.compressedHash = attachment.GetCompressedMD5().c_str(); | |
200 | |
201 if (backend_.addAttachment(payload_, id, &tmp) != 0) | |
202 { | |
203 throw OrthancException(ErrorCode_Plugin); | |
204 } | |
205 } | |
206 | |
207 | |
208 void OrthancPluginDatabase::AttachChild(int64_t parent, | |
209 int64_t child) | |
210 { | |
211 if (backend_.attachChild(payload_, parent, child) != 0) | |
212 { | |
213 throw OrthancException(ErrorCode_Plugin); | |
214 } | |
215 } | |
216 | |
217 | |
218 void OrthancPluginDatabase::ClearChanges() | |
219 { | |
220 if (backend_.clearChanges(payload_) != 0) | |
221 { | |
222 throw OrthancException(ErrorCode_Plugin); | |
223 } | |
224 } | |
225 | |
226 | |
227 void OrthancPluginDatabase::ClearExportedResources() | |
228 { | |
229 if (backend_.clearExportedResources(payload_) != 0) | |
230 { | |
231 throw OrthancException(ErrorCode_Plugin); | |
232 } | |
233 } | |
234 | |
235 | |
236 int64_t OrthancPluginDatabase::CreateResource(const std::string& publicId, | |
237 ResourceType type) | |
238 { | |
239 int64_t id; | |
240 | |
241 if (backend_.createResource(&id, payload_, publicId.c_str(), Convert(type)) != 0) | |
242 { | |
243 throw OrthancException(ErrorCode_Plugin); | |
244 } | |
245 | |
246 return id; | |
247 } | |
248 | |
249 | |
250 void OrthancPluginDatabase::DeleteAttachment(int64_t id, | |
251 FileContentType attachment) | |
252 { | |
253 if (backend_.deleteAttachment(payload_, id, static_cast<int32_t>(attachment)) != 0) | |
254 { | |
255 throw OrthancException(ErrorCode_Plugin); | |
256 } | |
257 } | |
258 | |
259 | |
260 void OrthancPluginDatabase::DeleteMetadata(int64_t id, | |
261 MetadataType type) | |
262 { | |
263 if (backend_.deleteMetadata(payload_, id, static_cast<int32_t>(type)) != 0) | |
264 { | |
265 throw OrthancException(ErrorCode_Plugin); | |
266 } | |
267 } | |
268 | |
269 | |
270 void OrthancPluginDatabase::DeleteResource(int64_t id) | |
271 { | |
272 if (backend_.deleteResource(payload_, id) != 0) | |
273 { | |
274 throw OrthancException(ErrorCode_Plugin); | |
275 } | |
276 } | |
277 | |
278 | |
279 void OrthancPluginDatabase::GetAllMetadata(std::map<MetadataType, std::string>& target, | |
280 int64_t id) | |
281 { | |
282 std::list<MetadataType> metadata; | |
283 ListAvailableMetadata(metadata, id); | |
284 | |
285 target.clear(); | |
286 | |
287 for (std::list<MetadataType>::const_iterator | |
288 it = metadata.begin(); it != metadata.end(); it++) | |
289 { | |
290 std::string value; | |
291 if (!LookupMetadata(value, id, *it)) | |
292 { | |
293 throw OrthancException(ErrorCode_Plugin); | |
294 } | |
295 | |
296 target[*it] = value; | |
297 } | |
298 } | |
299 | |
300 | |
301 void OrthancPluginDatabase::GetAllPublicIds(std::list<std::string>& target, | |
302 ResourceType resourceType) | |
303 { | |
304 ResetAnswers(); | |
305 | |
306 if (backend_.getAllPublicIds(GetContext(), payload_, Convert(resourceType)) != 0) | |
307 { | |
308 throw OrthancException(ErrorCode_Plugin); | |
309 } | |
310 | |
311 ForwardAnswers(target); | |
312 } | |
313 | |
314 | |
315 | |
316 void OrthancPluginDatabase::GetChanges(std::list<ServerIndexChange>& target /*out*/, | |
317 bool& done /*out*/, | |
318 int64_t since, | |
319 uint32_t maxResults) | |
320 { | |
321 ResetAnswers(); | |
322 answerChanges_ = ⌖ | |
323 answerDone_ = &done; | |
324 done = false; | |
325 | |
326 if (backend_.getChanges(GetContext(), payload_, since, maxResults) != 0) | |
327 { | |
328 throw OrthancException(ErrorCode_Plugin); | |
329 } | |
330 } | |
331 | |
332 | |
333 void OrthancPluginDatabase::GetChildrenInternalId(std::list<int64_t>& target, | |
334 int64_t id) | |
335 { | |
336 ResetAnswers(); | |
337 | |
338 if (backend_.getChildrenInternalId(GetContext(), payload_, id) != 0) | |
339 { | |
340 throw OrthancException(ErrorCode_Plugin); | |
341 } | |
342 | |
343 ForwardAnswers(target); | |
344 } | |
345 | |
346 | |
347 void OrthancPluginDatabase::GetChildrenPublicId(std::list<std::string>& target, | |
348 int64_t id) | |
349 { | |
350 ResetAnswers(); | |
351 | |
352 if (backend_.getChildrenPublicId(GetContext(), payload_, id) != 0) | |
353 { | |
354 throw OrthancException(ErrorCode_Plugin); | |
355 } | |
356 | |
357 ForwardAnswers(target); | |
358 } | |
359 | |
360 | |
361 void OrthancPluginDatabase::GetExportedResources(std::list<ExportedResource>& target /*out*/, | |
362 bool& done /*out*/, | |
363 int64_t since, | |
364 uint32_t maxResults) | |
365 { | |
366 ResetAnswers(); | |
367 answerExportedResources_ = ⌖ | |
368 answerDone_ = &done; | |
369 done = false; | |
370 | |
371 if (backend_.getExportedResources(GetContext(), payload_, since, maxResults) != 0) | |
372 { | |
373 throw OrthancException(ErrorCode_Plugin); | |
374 } | |
375 } | |
376 | |
377 | |
378 void OrthancPluginDatabase::GetLastChange(std::list<ServerIndexChange>& target /*out*/) | |
379 { | |
380 bool ignored = false; | |
381 | |
382 ResetAnswers(); | |
383 answerChanges_ = ⌖ | |
384 answerDone_ = &ignored; | |
385 | |
386 if (backend_.getLastChange(GetContext(), payload_) != 0) | |
387 { | |
388 throw OrthancException(ErrorCode_Plugin); | |
389 } | |
390 } | |
391 | |
392 | |
393 void OrthancPluginDatabase::GetLastExportedResource(std::list<ExportedResource>& target /*out*/) | |
394 { | |
395 bool ignored = false; | |
396 | |
397 ResetAnswers(); | |
398 answerExportedResources_ = ⌖ | |
399 answerDone_ = &ignored; | |
400 | |
401 if (backend_.getLastExportedResource(GetContext(), payload_) != 0) | |
402 { | |
403 throw OrthancException(ErrorCode_Plugin); | |
404 } | |
405 } | |
406 | |
407 | |
408 void OrthancPluginDatabase::GetMainDicomTags(DicomMap& map, | |
409 int64_t id) | |
410 { | |
411 ResetAnswers(); | |
412 answerDicomMap_ = ↦ | |
413 | |
414 if (backend_.getMainDicomTags(GetContext(), payload_, id) != 0) | |
415 { | |
416 throw OrthancException(ErrorCode_Plugin); | |
417 } | |
418 } | |
419 | |
420 | |
421 std::string OrthancPluginDatabase::GetPublicId(int64_t resourceId) | |
422 { | |
423 ResetAnswers(); | |
424 std::string s; | |
425 | |
426 if (backend_.getPublicId(GetContext(), payload_, resourceId) != 0 || | |
427 !ForwardSingleAnswer(s)) | |
428 { | |
429 throw OrthancException(ErrorCode_Plugin); | |
430 } | |
431 | |
432 return s; | |
433 } | |
434 | |
435 | |
436 uint64_t OrthancPluginDatabase::GetResourceCount(ResourceType resourceType) | |
437 { | |
438 uint64_t count; | |
439 | |
440 if (backend_.getResourceCount(&count, payload_, Convert(resourceType)) != 0) | |
441 { | |
442 throw OrthancException(ErrorCode_Plugin); | |
443 } | |
444 | |
445 return count; | |
446 } | |
447 | |
448 | |
449 ResourceType OrthancPluginDatabase::GetResourceType(int64_t resourceId) | |
450 { | |
451 OrthancPluginResourceType type; | |
452 | |
453 if (backend_.getResourceType(&type, payload_, resourceId) != 0) | |
454 { | |
455 throw OrthancException(ErrorCode_Plugin); | |
456 } | |
457 | |
458 return Convert(type); | |
459 } | |
460 | |
461 | |
462 uint64_t OrthancPluginDatabase::GetTotalCompressedSize() | |
463 { | |
464 uint64_t size; | |
465 | |
466 if (backend_.getTotalCompressedSize(&size, payload_) != 0) | |
467 { | |
468 throw OrthancException(ErrorCode_Plugin); | |
469 } | |
470 | |
471 return size; | |
472 } | |
473 | |
474 | |
475 uint64_t OrthancPluginDatabase::GetTotalUncompressedSize() | |
476 { | |
477 uint64_t size; | |
478 | |
479 if (backend_.getTotalUncompressedSize(&size, payload_) != 0) | |
480 { | |
481 throw OrthancException(ErrorCode_Plugin); | |
482 } | |
483 | |
484 return size; | |
485 } | |
486 | |
487 | |
488 bool OrthancPluginDatabase::IsExistingResource(int64_t internalId) | |
489 { | |
490 int32_t existing; | |
491 | |
492 if (backend_.isExistingResource(&existing, payload_, internalId) != 0) | |
493 { | |
494 throw OrthancException(ErrorCode_Plugin); | |
495 } | |
496 | |
497 return existing; | |
498 } | |
499 | |
500 | |
501 bool OrthancPluginDatabase::IsProtectedPatient(int64_t internalId) | |
502 { | |
503 int32_t isProtected; | |
504 | |
505 if (backend_.isProtectedPatient(&isProtected, payload_, internalId) != 0) | |
506 { | |
507 throw OrthancException(ErrorCode_Plugin); | |
508 } | |
509 | |
510 return isProtected; | |
511 } | |
512 | |
513 | |
514 void OrthancPluginDatabase::ListAvailableMetadata(std::list<MetadataType>& target, | |
515 int64_t id) | |
516 { | |
517 ResetAnswers(); | |
518 | |
519 if (backend_.listAvailableMetadata(GetContext(), payload_, id) != 0) | |
520 { | |
521 throw OrthancException(ErrorCode_Plugin); | |
522 } | |
523 | |
524 if (type_ != _OrthancPluginDatabaseAnswerType_None && | |
525 type_ != _OrthancPluginDatabaseAnswerType_Int32) | |
526 { | |
527 throw OrthancException(ErrorCode_Plugin); | |
528 } | |
529 | |
530 target.clear(); | |
531 | |
532 if (type_ == _OrthancPluginDatabaseAnswerType_Int32) | |
533 { | |
534 for (std::list<int32_t>::const_iterator | |
535 it = answerInt32_.begin(); it != answerInt32_.end(); it++) | |
536 { | |
537 target.push_back(static_cast<MetadataType>(*it)); | |
538 } | |
539 } | |
540 } | |
541 | |
542 | |
543 void OrthancPluginDatabase::ListAvailableAttachments(std::list<FileContentType>& target, | |
544 int64_t id) | |
545 { | |
546 ResetAnswers(); | |
547 | |
548 if (backend_.listAvailableAttachments(GetContext(), payload_, id) != 0) | |
549 { | |
550 throw OrthancException(ErrorCode_Plugin); | |
551 } | |
552 | |
553 if (type_ != _OrthancPluginDatabaseAnswerType_None && | |
554 type_ != _OrthancPluginDatabaseAnswerType_Int32) | |
555 { | |
556 throw OrthancException(ErrorCode_Plugin); | |
557 } | |
558 | |
559 target.clear(); | |
560 | |
561 if (type_ == _OrthancPluginDatabaseAnswerType_Int32) | |
562 { | |
563 for (std::list<int32_t>::const_iterator | |
564 it = answerInt32_.begin(); it != answerInt32_.end(); it++) | |
565 { | |
566 target.push_back(static_cast<FileContentType>(*it)); | |
567 } | |
568 } | |
569 } | |
570 | |
571 | |
572 void OrthancPluginDatabase::LogChange(int64_t internalId, | |
573 const ServerIndexChange& change) | |
574 { | |
575 OrthancPluginChange tmp; | |
576 tmp.seq = change.GetSeq(); | |
577 tmp.changeType = static_cast<int32_t>(change.GetChangeType()); | |
578 tmp.resourceType = Convert(change.GetResourceType()); | |
579 tmp.publicId = change.GetPublicId().c_str(); | |
580 tmp.date = change.GetDate().c_str(); | |
581 | |
582 if (backend_.logChange(payload_, &tmp) != 0) | |
583 { | |
584 throw OrthancException(ErrorCode_Plugin); | |
585 } | |
586 } | |
587 | |
588 | |
589 void OrthancPluginDatabase::LogExportedResource(const ExportedResource& resource) | |
590 { | |
591 OrthancPluginExportedResource tmp; | |
592 tmp.seq = resource.GetSeq(); | |
593 tmp.resourceType = Convert(resource.GetResourceType()); | |
594 tmp.publicId = resource.GetPublicId().c_str(); | |
595 tmp.modality = resource.GetModality().c_str(); | |
596 tmp.date = resource.GetDate().c_str(); | |
597 tmp.patientId = resource.GetPatientId().c_str(); | |
598 tmp.studyInstanceUid = resource.GetStudyInstanceUid().c_str(); | |
599 tmp.seriesInstanceUid = resource.GetSeriesInstanceUid().c_str(); | |
600 tmp.sopInstanceUid = resource.GetSopInstanceUid().c_str(); | |
601 | |
602 if (backend_.logExportedResource(payload_, &tmp) != 0) | |
603 { | |
604 throw OrthancException(ErrorCode_Plugin); | |
605 } | |
606 } | |
607 | |
608 | |
609 bool OrthancPluginDatabase::LookupAttachment(FileInfo& attachment, | |
610 int64_t id, | |
611 FileContentType contentType) | |
612 { | |
613 ResetAnswers(); | |
614 | |
615 if (backend_.lookupAttachment(GetContext(), payload_, id, static_cast<int32_t>(contentType))) | |
616 { | |
617 throw OrthancException(ErrorCode_Plugin); | |
618 } | |
619 | |
620 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
621 { | |
622 return false; | |
623 } | |
624 else if (type_ == _OrthancPluginDatabaseAnswerType_Attachment && | |
625 answerAttachments_.size() == 1) | |
626 { | |
627 attachment = answerAttachments_.front(); | |
628 return true; | |
629 } | |
630 else | |
631 { | |
632 throw OrthancException(ErrorCode_Plugin); | |
633 } | |
634 } | |
635 | |
636 | |
637 bool OrthancPluginDatabase::LookupGlobalProperty(std::string& target, | |
638 GlobalProperty property) | |
639 { | |
640 ResetAnswers(); | |
641 | |
642 if (backend_.lookupGlobalProperty(GetContext(), payload_, | |
643 static_cast<int32_t>(property))) | |
644 { | |
645 throw OrthancException(ErrorCode_Plugin); | |
646 } | |
647 | |
648 return ForwardSingleAnswer(target); | |
649 } | |
650 | |
651 | |
652 void OrthancPluginDatabase::LookupIdentifier(std::list<int64_t>& target, | |
653 const DicomTag& tag, | |
654 const std::string& value) | |
655 { | |
656 ResetAnswers(); | |
657 | |
658 OrthancPluginDicomTag tmp; | |
659 tmp.group = tag.GetGroup(); | |
660 tmp.element = tag.GetElement(); | |
661 tmp.value = value.c_str(); | |
662 | |
663 if (backend_.lookupIdentifier(GetContext(), payload_, &tmp) != 0) | |
664 { | |
665 throw OrthancException(ErrorCode_Plugin); | |
666 } | |
667 | |
668 ForwardAnswers(target); | |
669 } | |
670 | |
671 | |
672 void OrthancPluginDatabase::LookupIdentifier(std::list<int64_t>& target, | |
673 const std::string& value) | |
674 { | |
675 ResetAnswers(); | |
676 | |
677 if (backend_.lookupIdentifier2(GetContext(), payload_, value.c_str()) != 0) | |
678 { | |
679 throw OrthancException(ErrorCode_Plugin); | |
680 } | |
681 | |
682 ForwardAnswers(target); | |
683 } | |
684 | |
685 | |
686 bool OrthancPluginDatabase::LookupMetadata(std::string& target, | |
687 int64_t id, | |
688 MetadataType type) | |
689 { | |
690 ResetAnswers(); | |
691 | |
692 if (backend_.lookupMetadata(GetContext(), payload_, id, static_cast<int32_t>(type))) | |
693 { | |
694 throw OrthancException(ErrorCode_Plugin); | |
695 } | |
696 | |
697 return ForwardSingleAnswer(target); | |
698 } | |
699 | |
700 | |
701 bool OrthancPluginDatabase::LookupParent(int64_t& parentId, | |
702 int64_t resourceId) | |
703 { | |
704 ResetAnswers(); | |
705 | |
706 if (backend_.lookupParent(GetContext(), payload_, resourceId)) | |
707 { | |
708 throw OrthancException(ErrorCode_Plugin); | |
709 } | |
710 | |
711 return ForwardSingleAnswer(parentId); | |
712 } | |
713 | |
714 | |
715 bool OrthancPluginDatabase::LookupResource(int64_t& id, | |
716 ResourceType& type, | |
717 const std::string& publicId) | |
718 { | |
719 ResetAnswers(); | |
720 | |
721 if (backend_.lookupResource(GetContext(), payload_, publicId.c_str())) | |
722 { | |
723 throw OrthancException(ErrorCode_Plugin); | |
724 } | |
725 | |
726 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
727 { | |
728 return false; | |
729 } | |
730 else if (type_ == _OrthancPluginDatabaseAnswerType_Resource && | |
731 answerResources_.size() == 1) | |
732 { | |
733 id = answerResources_.front().first; | |
734 type = answerResources_.front().second; | |
735 return true; | |
736 } | |
737 else | |
738 { | |
739 throw OrthancException(ErrorCode_Plugin); | |
740 } | |
741 } | |
742 | |
743 | |
744 bool OrthancPluginDatabase::SelectPatientToRecycle(int64_t& internalId) | |
745 { | |
746 ResetAnswers(); | |
747 | |
748 if (backend_.selectPatientToRecycle(GetContext(), payload_)) | |
749 { | |
750 throw OrthancException(ErrorCode_Plugin); | |
751 } | |
752 | |
753 return ForwardSingleAnswer(internalId); | |
754 } | |
755 | |
756 | |
757 bool OrthancPluginDatabase::SelectPatientToRecycle(int64_t& internalId, | |
758 int64_t patientIdToAvoid) | |
759 { | |
760 ResetAnswers(); | |
761 | |
762 if (backend_.selectPatientToRecycle2(GetContext(), payload_, patientIdToAvoid)) | |
763 { | |
764 throw OrthancException(ErrorCode_Plugin); | |
765 } | |
766 | |
767 return ForwardSingleAnswer(internalId); | |
768 } | |
769 | |
770 | |
771 void OrthancPluginDatabase::SetGlobalProperty(GlobalProperty property, | |
772 const std::string& value) | |
773 { | |
774 if (backend_.setGlobalProperty(payload_, static_cast<int32_t>(property), | |
775 value.c_str()) != 0) | |
776 { | |
777 throw OrthancException(ErrorCode_Plugin); | |
778 } | |
779 } | |
780 | |
781 | |
782 void OrthancPluginDatabase::SetMainDicomTag(int64_t id, | |
783 const DicomTag& tag, | |
784 const std::string& value) | |
785 { | |
786 int32_t status; | |
787 OrthancPluginDicomTag tmp; | |
788 tmp.group = tag.GetGroup(); | |
789 tmp.element = tag.GetElement(); | |
790 tmp.value = value.c_str(); | |
791 | |
792 if (tag.IsIdentifier()) | |
793 { | |
794 status = backend_.setIdentifierTag(payload_, id, &tmp); | |
795 } | |
796 else | |
797 { | |
798 status = backend_.setMainDicomTag(payload_, id, &tmp); | |
799 } | |
800 | |
801 if (status != 0) | |
802 { | |
803 throw OrthancException(ErrorCode_Plugin); | |
804 } | |
805 } | |
806 | |
807 | |
808 void OrthancPluginDatabase::SetMetadata(int64_t id, | |
809 MetadataType type, | |
810 const std::string& value) | |
811 { | |
812 if (backend_.setMetadata(payload_, id, static_cast<int32_t>(type), | |
813 value.c_str()) != 0) | |
814 { | |
815 throw OrthancException(ErrorCode_Plugin); | |
816 } | |
817 } | |
818 | |
819 | |
820 void OrthancPluginDatabase::SetProtectedPatient(int64_t internalId, | |
821 bool isProtected) | |
822 { | |
823 if (backend_.setProtectedPatient(payload_, internalId, isProtected) != 0) | |
824 { | |
825 throw OrthancException(ErrorCode_Plugin); | |
826 } | |
827 } | |
828 | |
829 | |
830 class OrthancPluginDatabase::Transaction : public SQLite::ITransaction | |
831 { | |
832 private: | |
833 const OrthancPluginDatabaseBackend& backend_; | |
834 void* payload_; | |
835 | |
836 public: | |
837 Transaction(const OrthancPluginDatabaseBackend& backend, | |
838 void* payload) : | |
839 backend_(backend), | |
840 payload_(payload) | |
841 { | |
842 } | |
843 | |
844 virtual void Begin() | |
845 { | |
846 if (backend_.startTransaction(payload_) != 0) | |
847 { | |
848 throw OrthancException(ErrorCode_Plugin); | |
849 } | |
850 } | |
851 | |
852 virtual void Rollback() | |
853 { | |
854 if (backend_.rollbackTransaction(payload_) != 0) | |
855 { | |
856 throw OrthancException(ErrorCode_Plugin); | |
857 } | |
858 } | |
859 | |
860 virtual void Commit() | |
861 { | |
862 if (backend_.commitTransaction(payload_) != 0) | |
863 { | |
864 throw OrthancException(ErrorCode_Plugin); | |
865 } | |
866 } | |
867 }; | |
868 | |
869 | |
870 SQLite::ITransaction* OrthancPluginDatabase::StartTransaction() | |
871 { | |
872 return new Transaction(backend_, payload_); | |
873 } | |
874 | |
875 | |
876 static void ProcessEvent(IServerIndexListener& listener, | |
877 const _OrthancPluginDatabaseAnswer& answer) | |
878 { | |
879 switch (answer.type) | |
880 { | |
881 case _OrthancPluginDatabaseAnswerType_DeletedAttachment: | |
882 { | |
883 const OrthancPluginAttachment& attachment = | |
884 *reinterpret_cast<const OrthancPluginAttachment*>(answer.valueGeneric); | |
885 listener.SignalFileDeleted(Convert(attachment)); | |
886 break; | |
887 } | |
888 | |
889 case _OrthancPluginDatabaseAnswerType_RemainingAncestor: | |
890 { | |
891 ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32)); | |
892 listener.SignalRemainingAncestor(type, answer.valueString); | |
893 break; | |
894 } | |
895 | |
896 case _OrthancPluginDatabaseAnswerType_DeletedResource: | |
897 { | |
898 ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32)); | |
899 ServerIndexChange change(ChangeType_Deleted, type, answer.valueString); | |
900 listener.SignalChange(change); | |
901 break; | |
902 } | |
903 | |
904 default: | |
905 throw OrthancException(ErrorCode_Plugin); | |
906 } | |
907 } | |
908 | |
909 | |
910 void OrthancPluginDatabase::AnswerReceived(const _OrthancPluginDatabaseAnswer& answer) | |
911 { | |
912 if (answer.type == _OrthancPluginDatabaseAnswerType_None) | |
913 { | |
914 throw OrthancException(ErrorCode_Plugin); | |
915 } | |
916 | |
917 if (answer.type == _OrthancPluginDatabaseAnswerType_DeletedAttachment || | |
918 answer.type == _OrthancPluginDatabaseAnswerType_DeletedResource || | |
919 answer.type == _OrthancPluginDatabaseAnswerType_RemainingAncestor) | |
920 { | |
921 assert(listener_ != NULL); | |
922 ProcessEvent(*listener_, answer); | |
923 return; | |
924 } | |
925 | |
926 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
927 { | |
928 type_ = answer.type; | |
929 | |
930 switch (type_) | |
931 { | |
932 case _OrthancPluginDatabaseAnswerType_Int32: | |
933 answerInt32_.clear(); | |
934 break; | |
935 | |
936 case _OrthancPluginDatabaseAnswerType_Int64: | |
937 answerInt64_.clear(); | |
938 break; | |
939 | |
940 case _OrthancPluginDatabaseAnswerType_Resource: | |
941 answerResources_.clear(); | |
942 break; | |
943 | |
944 case _OrthancPluginDatabaseAnswerType_Attachment: | |
945 answerAttachments_.clear(); | |
946 break; | |
947 | |
948 case _OrthancPluginDatabaseAnswerType_String: | |
949 answerStrings_.clear(); | |
950 break; | |
951 | |
952 case _OrthancPluginDatabaseAnswerType_DicomTag: | |
953 assert(answerDicomMap_ != NULL); | |
954 answerDicomMap_->Clear(); | |
955 break; | |
956 | |
957 case _OrthancPluginDatabaseAnswerType_Change: | |
958 assert(answerChanges_ != NULL); | |
959 answerChanges_->clear(); | |
960 break; | |
961 | |
962 case _OrthancPluginDatabaseAnswerType_ExportedResource: | |
963 assert(answerExportedResources_ != NULL); | |
964 answerExportedResources_->clear(); | |
965 break; | |
966 | |
967 default: | |
968 LOG(ERROR) << "Unhandled type of answer for custom index plugin: " << answer.type; | |
969 throw OrthancException(ErrorCode_Plugin); | |
970 } | |
971 } | |
972 else if (type_ != answer.type) | |
973 { | |
974 LOG(ERROR) << "Error in the plugin protocol: Cannot change the answer type"; | |
975 throw OrthancException(ErrorCode_Plugin); | |
976 } | |
977 | |
978 switch (answer.type) | |
979 { | |
980 case _OrthancPluginDatabaseAnswerType_Int32: | |
981 { | |
982 answerInt32_.push_back(answer.valueInt32); | |
983 break; | |
984 } | |
985 | |
986 case _OrthancPluginDatabaseAnswerType_Int64: | |
987 { | |
988 answerInt64_.push_back(answer.valueInt64); | |
989 break; | |
990 } | |
991 | |
992 case _OrthancPluginDatabaseAnswerType_Resource: | |
993 { | |
994 OrthancPluginResourceType type = static_cast<OrthancPluginResourceType>(answer.valueInt32); | |
995 answerResources_.push_back(std::make_pair(answer.valueInt64, Convert(type))); | |
996 break; | |
997 } | |
998 | |
999 case _OrthancPluginDatabaseAnswerType_Attachment: | |
1000 { | |
1001 const OrthancPluginAttachment& attachment = | |
1002 *reinterpret_cast<const OrthancPluginAttachment*>(answer.valueGeneric); | |
1003 | |
1004 answerAttachments_.push_back(Convert(attachment)); | |
1005 break; | |
1006 } | |
1007 | |
1008 case _OrthancPluginDatabaseAnswerType_DicomTag: | |
1009 { | |
1010 const OrthancPluginDicomTag& tag = *reinterpret_cast<const OrthancPluginDicomTag*>(answer.valueGeneric); | |
1011 assert(answerDicomMap_ != NULL); | |
1012 answerDicomMap_->SetValue(tag.group, tag.element, std::string(tag.value)); | |
1013 break; | |
1014 } | |
1015 | |
1016 case _OrthancPluginDatabaseAnswerType_String: | |
1017 { | |
1018 if (answer.valueString == NULL) | |
1019 { | |
1020 throw OrthancException(ErrorCode_Plugin); | |
1021 } | |
1022 | |
1023 if (type_ == _OrthancPluginDatabaseAnswerType_None) | |
1024 { | |
1025 type_ = _OrthancPluginDatabaseAnswerType_String; | |
1026 answerStrings_.clear(); | |
1027 } | |
1028 else if (type_ != _OrthancPluginDatabaseAnswerType_String) | |
1029 { | |
1030 throw OrthancException(ErrorCode_Plugin); | |
1031 } | |
1032 | |
1033 answerStrings_.push_back(std::string(answer.valueString)); | |
1034 break; | |
1035 } | |
1036 | |
1037 case _OrthancPluginDatabaseAnswerType_Change: | |
1038 { | |
1039 assert(answerDone_ != NULL); | |
1040 if (answer.valueUint32 == 1) | |
1041 { | |
1042 *answerDone_ = true; | |
1043 } | |
1044 else if (*answerDone_) | |
1045 { | |
1046 throw OrthancException(ErrorCode_Plugin); | |
1047 } | |
1048 else | |
1049 { | |
1050 const OrthancPluginChange& change = *reinterpret_cast<const OrthancPluginChange*>(answer.valueGeneric); | |
1051 assert(answerChanges_ != NULL); | |
1052 answerChanges_->push_back | |
1053 (ServerIndexChange(change.seq, | |
1054 static_cast<ChangeType>(change.changeType), | |
1055 Convert(change.resourceType), | |
1056 change.publicId, | |
1057 change.date)); | |
1058 } | |
1059 | |
1060 break; | |
1061 } | |
1062 | |
1063 case _OrthancPluginDatabaseAnswerType_ExportedResource: | |
1064 { | |
1065 assert(answerDone_ != NULL); | |
1066 if (answer.valueUint32 == 1) | |
1067 { | |
1068 *answerDone_ = true; | |
1069 } | |
1070 else if (*answerDone_) | |
1071 { | |
1072 throw OrthancException(ErrorCode_Plugin); | |
1073 } | |
1074 else | |
1075 { | |
1076 const OrthancPluginExportedResource& exported = | |
1077 *reinterpret_cast<const OrthancPluginExportedResource*>(answer.valueGeneric); | |
1078 assert(answerExportedResources_ != NULL); | |
1079 answerExportedResources_->push_back | |
1080 (ExportedResource(exported.seq, | |
1081 Convert(exported.resourceType), | |
1082 exported.publicId, | |
1083 exported.modality, | |
1084 exported.date, | |
1085 exported.patientId, | |
1086 exported.studyInstanceUid, | |
1087 exported.seriesInstanceUid, | |
1088 exported.sopInstanceUid)); | |
1089 } | |
1090 | |
1091 break; | |
1092 } | |
1093 | |
1094 default: | |
1095 LOG(ERROR) << "Unhandled type of answer for custom index plugin: " << answer.type; | |
1096 throw OrthancException(ErrorCode_Plugin); | |
1097 } | |
1098 } | |
1099 } |