Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/FindResponse.cpp @ 5586:fc3914c07dd3 find-refactoring
refactoring FindResponse
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 03 May 2024 17:02:02 +0200 |
parents | 74cc31c8db2b |
children | 1b0fc6685f57 |
comparison
equal
deleted
inserted
replaced
5583:74cc31c8db2b | 5586:fc3914c07dd3 |
---|---|
28 #include <cassert> | 28 #include <cassert> |
29 | 29 |
30 | 30 |
31 namespace Orthanc | 31 namespace Orthanc |
32 { | 32 { |
33 static void ExtractOrthancIdentifiers(OrthancIdentifiers& identifiers, | 33 class FindResponse::DicomTagsAtLevel::DicomValue : public boost::noncopyable |
34 ResourceType level, | 34 { |
35 const DicomMap& dicom) | 35 public: |
36 enum ValueType | |
37 { | |
38 ValueType_String, | |
39 ValueType_Null | |
40 }; | |
41 | |
42 private: | |
43 ValueType type_; | |
44 std::string value_; | |
45 | |
46 public: | |
47 DicomValue(ValueType type, | |
48 const std::string& value) : | |
49 type_(type), | |
50 value_(value) | |
51 { | |
52 } | |
53 | |
54 ValueType GetType() const | |
55 { | |
56 return type_; | |
57 } | |
58 | |
59 const std::string& GetValue() const | |
60 { | |
61 switch (type_) | |
62 { | |
63 case ValueType_Null: | |
64 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
65 | |
66 case ValueType_String: | |
67 return value_; | |
68 | |
69 default: | |
70 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
71 } | |
72 } | |
73 }; | |
74 | |
75 | |
76 FindResponse::DicomTagsAtLevel::~DicomTagsAtLevel() | |
77 { | |
78 for (Content::iterator it = content_.begin(); it != content_.end(); ++it) | |
79 { | |
80 assert(it->second != NULL); | |
81 delete it->second; | |
82 } | |
83 } | |
84 | |
85 | |
86 void FindResponse::DicomTagsAtLevel::AddNullValue(uint16_t group, | |
87 uint16_t element) | |
88 { | |
89 const DicomTag tag(group, element); | |
90 | |
91 if (content_.find(tag) == content_.end()) | |
92 { | |
93 content_[tag] = new DicomValue(DicomValue::ValueType_Null, ""); | |
94 } | |
95 else | |
96 { | |
97 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
98 } | |
99 } | |
100 | |
101 | |
102 void FindResponse::DicomTagsAtLevel::AddStringValue(uint16_t group, | |
103 uint16_t element, | |
104 const std::string& value) | |
105 { | |
106 const DicomTag tag(group, element); | |
107 | |
108 if (content_.find(tag) == content_.end()) | |
109 { | |
110 content_[tag] = new DicomValue(DicomValue::ValueType_String, value); | |
111 } | |
112 else | |
113 { | |
114 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
115 } | |
116 } | |
117 | |
118 | |
119 void FindResponse::DicomTagsAtLevel::Fill(DicomMap& target) const | |
120 { | |
121 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) | |
122 { | |
123 assert(it->second != NULL); | |
124 | |
125 switch (it->second->GetType()) | |
126 { | |
127 case DicomValue::ValueType_String: | |
128 target.SetValue(it->first, it->second->GetValue(), false /* not binary */); | |
129 break; | |
130 | |
131 case DicomValue::ValueType_Null: | |
132 target.SetNullValue(it->first); | |
133 break; | |
134 | |
135 default: | |
136 throw OrthancException(ErrorCode_InternalError); | |
137 } | |
138 } | |
139 } | |
140 | |
141 | |
142 void FindResponse::ChildrenAtLevel::AddIdentifier(const std::string& identifier) | |
143 { | |
144 if (identifiers_.find(identifier) == identifiers_.end()) | |
145 { | |
146 identifiers_.insert(identifier); | |
147 } | |
148 else | |
149 { | |
150 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
151 } | |
152 } | |
153 | |
154 | |
155 FindResponse::DicomTagsAtLevel& FindResponse::Item::GetDicomTagsAtLevel(ResourceType level) | |
36 { | 156 { |
37 switch (level) | 157 switch (level) |
38 { | 158 { |
39 case ResourceType_Patient: | 159 case ResourceType_Patient: |
40 { | 160 return patientTags_; |
41 std::string patientId; | 161 |
42 if (!dicom.LookupStringValue(patientId, Orthanc::DICOM_TAG_PATIENT_ID, false)) | 162 case ResourceType_Study: |
43 { | 163 return studyTags_; |
44 throw OrthancException(ErrorCode_ParameterOutOfRange); | 164 |
165 case ResourceType_Series: | |
166 return seriesTags_; | |
167 | |
168 case ResourceType_Instance: | |
169 return instanceTags_; | |
170 | |
171 default: | |
172 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
173 } | |
174 } | |
175 | |
176 | |
177 FindResponse::ChildrenAtLevel& FindResponse::Item::GetChildrenAtLevel(ResourceType level) | |
178 { | |
179 switch (level) | |
180 { | |
181 case ResourceType_Study: | |
182 if (level_ == ResourceType_Patient) | |
183 { | |
184 return childrenStudies_; | |
45 } | 185 } |
46 else | 186 else |
47 { | 187 { |
48 DicomInstanceHasher hasher(patientId, "", "", ""); | 188 throw OrthancException(ErrorCode_BadParameterType); |
49 identifiers.SetPatientId(hasher.HashPatient()); | 189 } |
50 } | 190 |
51 break; | 191 case ResourceType_Series: |
52 } | 192 if (level_ == ResourceType_Patient || |
53 | 193 level_ == ResourceType_Study) |
54 case ResourceType_Study: | 194 { |
55 { | 195 return childrenSeries_; |
56 std::string patientId, studyInstanceUid; | |
57 if (!dicom.LookupStringValue(patientId, Orthanc::DICOM_TAG_PATIENT_ID, false) || | |
58 !dicom.LookupStringValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false)) | |
59 { | |
60 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
61 } | 196 } |
62 else | 197 else |
63 { | 198 { |
64 DicomInstanceHasher hasher(patientId, studyInstanceUid, "", ""); | 199 throw OrthancException(ErrorCode_BadParameterType); |
65 identifiers.SetPatientId(hasher.HashPatient()); | 200 } |
66 identifiers.SetStudyId(hasher.HashStudy()); | 201 |
67 } | 202 case ResourceType_Instance: |
68 break; | 203 if (level_ == ResourceType_Patient || |
69 } | 204 level_ == ResourceType_Study || |
70 | 205 level_ == ResourceType_Series) |
71 case ResourceType_Series: | 206 { |
72 { | 207 return childrenInstances_; |
73 std::string patientId, studyInstanceUid, seriesInstanceUid; | |
74 if (!dicom.LookupStringValue(patientId, Orthanc::DICOM_TAG_PATIENT_ID, false) || | |
75 !dicom.LookupStringValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false) || | |
76 !dicom.LookupStringValue(seriesInstanceUid, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, false)) | |
77 { | |
78 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
79 } | 208 } |
80 else | 209 else |
81 { | 210 { |
82 DicomInstanceHasher hasher(patientId, studyInstanceUid, seriesInstanceUid, ""); | 211 throw OrthancException(ErrorCode_BadParameterType); |
83 identifiers.SetPatientId(hasher.HashPatient()); | 212 } |
84 identifiers.SetStudyId(hasher.HashStudy()); | |
85 identifiers.SetSeriesId(hasher.HashSeries()); | |
86 } | |
87 break; | |
88 } | |
89 | |
90 case ResourceType_Instance: | |
91 { | |
92 std::string patientId, studyInstanceUid, seriesInstanceUid, sopInstanceUid; | |
93 if (!dicom.LookupStringValue(patientId, Orthanc::DICOM_TAG_PATIENT_ID, false) || | |
94 !dicom.LookupStringValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false) || | |
95 !dicom.LookupStringValue(seriesInstanceUid, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, false) || | |
96 !dicom.LookupStringValue(sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) | |
97 { | |
98 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
99 } | |
100 else | |
101 { | |
102 DicomInstanceHasher hasher(patientId, studyInstanceUid, seriesInstanceUid, sopInstanceUid); | |
103 identifiers.SetPatientId(hasher.HashPatient()); | |
104 identifiers.SetStudyId(hasher.HashStudy()); | |
105 identifiers.SetSeriesId(hasher.HashSeries()); | |
106 identifiers.SetInstanceId(hasher.HashInstance()); | |
107 } | |
108 break; | |
109 } | |
110 | 213 |
111 default: | 214 default: |
112 throw OrthancException(ErrorCode_NotImplemented); | 215 throw OrthancException(ErrorCode_ParameterOutOfRange); |
113 } | |
114 } | |
115 | |
116 | |
117 FindResponse::Item::Item(ResourceType level, | |
118 DicomMap* dicomMap /* takes ownership */) : | |
119 dicomMap_(dicomMap) | |
120 { | |
121 if (dicomMap == NULL) | |
122 { | |
123 throw OrthancException(ErrorCode_NullPointer); | |
124 } | |
125 else | |
126 { | |
127 ExtractOrthancIdentifiers(identifiers_, level, *dicomMap); | |
128 } | 216 } |
129 } | 217 } |
130 | 218 |
131 | 219 |
132 void FindResponse::Item::AddMetadata(MetadataType metadata, | 220 void FindResponse::Item::AddMetadata(MetadataType metadata, |
168 { | 256 { |
169 target.insert(it->first); | 257 target.insert(it->first); |
170 } | 258 } |
171 } | 259 } |
172 | 260 |
173 | 261 const std::string& FindResponse::Item::GetParentIdentifier() const |
174 const DicomMap& FindResponse::Item::GetDicomMap() const | 262 { |
175 { | 263 if (level_ == ResourceType_Patient) |
176 if (dicomMap_.get() == NULL) | 264 { |
177 { | 265 throw OrthancException(ErrorCode_BadParameterType); |
178 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 266 } |
179 } | 267 else if (HasParentIdentifier()) |
180 else | 268 { |
181 { | 269 return *parentIdentifier_; |
182 return *dicomMap_; | 270 } |
271 else | |
272 { | |
273 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
274 } | |
275 } | |
276 | |
277 | |
278 void FindResponse::Item::SetParentIdentifier(const std::string& id) | |
279 { | |
280 if (level_ == ResourceType_Patient) | |
281 { | |
282 throw OrthancException(ErrorCode_BadParameterType); | |
283 } | |
284 else if (HasParentIdentifier()) | |
285 { | |
286 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
287 } | |
288 else | |
289 { | |
290 parentIdentifier_.reset(new std::string(id)); | |
291 } | |
292 } | |
293 | |
294 | |
295 bool FindResponse::Item::HasParentIdentifier() const | |
296 { | |
297 if (level_ == ResourceType_Patient) | |
298 { | |
299 throw OrthancException(ErrorCode_BadParameterType); | |
300 } | |
301 else | |
302 { | |
303 return parentIdentifier_.get() != NULL; | |
304 } | |
305 } | |
306 | |
307 | |
308 void FindResponse::Item::AddLabel(const std::string& label) | |
309 { | |
310 if (labels_.find(label) == labels_.end()) | |
311 { | |
312 labels_.insert(label); | |
313 } | |
314 else | |
315 { | |
316 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
317 } | |
318 } | |
319 | |
320 | |
321 void FindResponse::Item::AddAttachment(const FileInfo& attachment) | |
322 { | |
323 if (attachments_.find(attachment.GetContentType()) == attachments_.end()) | |
324 { | |
325 attachments_[attachment.GetContentType()] = attachment; | |
326 } | |
327 else | |
328 { | |
329 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
330 } | |
331 } | |
332 | |
333 | |
334 bool FindResponse::Item::LookupAttachment(FileInfo& target, FileContentType type) const | |
335 { | |
336 std::map<FileContentType, FileInfo>::const_iterator it = attachments_.find(type); | |
337 if (it != attachments_.end()) | |
338 { | |
339 target = it->second; | |
340 return true; | |
341 } | |
342 else | |
343 { | |
344 return false; | |
183 } | 345 } |
184 } | 346 } |
185 | 347 |
186 | 348 |
187 FindResponse::~FindResponse() | 349 FindResponse::~FindResponse() |
194 } | 356 } |
195 | 357 |
196 | 358 |
197 void FindResponse::Add(Item* item /* takes ownership */) | 359 void FindResponse::Add(Item* item /* takes ownership */) |
198 { | 360 { |
361 std::unique_ptr<Item> protection(item); | |
362 | |
199 if (item == NULL) | 363 if (item == NULL) |
200 { | 364 { |
201 throw OrthancException(ErrorCode_NullPointer); | 365 throw OrthancException(ErrorCode_NullPointer); |
202 } | 366 } |
203 else | 367 else |
204 { | 368 { |
205 items_.push_back(item); | 369 const std::string& id = item->GetIdentifier(); |
370 | |
371 if (index_.find(id) == index_.end()) | |
372 { | |
373 items_.push_back(protection.release()); | |
374 index_[id] = item; | |
375 } | |
376 else | |
377 { | |
378 throw OrthancException(ErrorCode_BadSequenceOfCalls, "This resource has already been added: " + id); | |
379 } | |
206 } | 380 } |
207 } | 381 } |
208 | 382 |
209 | 383 |
210 const FindResponse::Item& FindResponse::GetItem(size_t index) const | 384 const FindResponse::Item& FindResponse::GetItem(size_t index) const |
218 assert(items_[index] != NULL); | 392 assert(items_[index] != NULL); |
219 return *items_[index]; | 393 return *items_[index]; |
220 } | 394 } |
221 } | 395 } |
222 | 396 |
223 void FindResponse::Item::AddDicomTag(uint16_t group, uint16_t element, const std::string& value, bool isBinary) | 397 |
224 { | 398 const FindResponse::Item* FindResponse::LookupItem(const std::string& id) const |
225 if (dicomMap_.get() == NULL) | 399 { |
226 { | 400 Index::const_iterator found = index_.find(id); |
227 dicomMap_.reset(new DicomMap()); | 401 |
228 } | 402 if (found == index_.end()) |
229 | 403 { |
230 dicomMap_->SetValue(group, element, value, isBinary); | 404 return NULL; |
231 } | 405 } |
232 | 406 else |
233 void FindResponse::Item::AddChild(const std::string& childId) | 407 { |
234 { | 408 assert(found->second != NULL); |
235 children_.push_back(childId); | 409 return found->second; |
236 } | 410 } |
237 | 411 } |
238 | |
239 } | 412 } |