Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/Compatibility/GenericFind.cpp @ 5596:81a29ad7fb4b find-refactoring
added possibility to retrieve main DICOM tags and metadata at any level
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 07 May 2024 18:44:53 +0200 |
parents | a87f2a56257d |
children | 6e2dad336446 |
comparison
equal
deleted
inserted
replaced
5595:a87f2a56257d | 5596:81a29ad7fb4b |
---|---|
23 #include "GenericFind.h" | 23 #include "GenericFind.h" |
24 | 24 |
25 #include "../../../../OrthancFramework/Sources/DicomFormat/DicomArray.h" | 25 #include "../../../../OrthancFramework/Sources/DicomFormat/DicomArray.h" |
26 #include "../../../../OrthancFramework/Sources/OrthancException.h" | 26 #include "../../../../OrthancFramework/Sources/OrthancException.h" |
27 | 27 |
28 #include <stack> | |
29 | |
28 | 30 |
29 namespace Orthanc | 31 namespace Orthanc |
30 { | 32 { |
31 namespace Compatibility | 33 namespace Compatibility |
32 { | 34 { |
57 throw OrthancException(ErrorCode_NotImplemented); // Not supported | 59 throw OrthancException(ErrorCode_NotImplemented); // Not supported |
58 } | 60 } |
59 } | 61 } |
60 | 62 |
61 | 63 |
64 void GenericFind::RetrieveMainDicomTags(FindResponse::Resource& target, | |
65 ResourceType level, | |
66 int64_t internalId) | |
67 { | |
68 DicomMap m; | |
69 transaction_.GetMainDicomTags(m, internalId); | |
70 | |
71 DicomArray a(m); | |
72 for (size_t i = 0; i < a.GetSize(); i++) | |
73 { | |
74 const DicomElement& element = a.GetElement(i); | |
75 if (element.GetValue().IsString()) | |
76 { | |
77 target.AddStringDicomTag(level, element.GetTag().GetGroup(), | |
78 element.GetTag().GetElement(), element.GetValue().GetContent()); | |
79 } | |
80 else | |
81 { | |
82 throw OrthancException(ErrorCode_BadParameterType); | |
83 } | |
84 } | |
85 } | |
86 | |
87 | |
88 static ResourceType GetTopLevelOfInterest(const FindRequest& request) | |
89 { | |
90 switch (request.GetLevel()) | |
91 { | |
92 case ResourceType_Patient: | |
93 return ResourceType_Patient; | |
94 | |
95 case ResourceType_Study: | |
96 if (request.IsRetrieveMainDicomTags(ResourceType_Patient) || | |
97 request.IsRetrieveMetadata(ResourceType_Patient)) | |
98 { | |
99 return ResourceType_Patient; | |
100 } | |
101 else | |
102 { | |
103 return ResourceType_Study; | |
104 } | |
105 | |
106 case ResourceType_Series: | |
107 if (request.IsRetrieveMainDicomTags(ResourceType_Patient) || | |
108 request.IsRetrieveMetadata(ResourceType_Patient)) | |
109 { | |
110 return ResourceType_Patient; | |
111 } | |
112 else if (request.IsRetrieveMainDicomTags(ResourceType_Study) || | |
113 request.IsRetrieveMetadata(ResourceType_Study)) | |
114 { | |
115 return ResourceType_Study; | |
116 } | |
117 else | |
118 { | |
119 return ResourceType_Series; | |
120 } | |
121 | |
122 case ResourceType_Instance: | |
123 if (request.IsRetrieveMainDicomTags(ResourceType_Patient) || | |
124 request.IsRetrieveMetadata(ResourceType_Patient)) | |
125 { | |
126 return ResourceType_Patient; | |
127 } | |
128 else if (request.IsRetrieveMainDicomTags(ResourceType_Study) || | |
129 request.IsRetrieveMetadata(ResourceType_Study)) | |
130 { | |
131 return ResourceType_Study; | |
132 } | |
133 else if (request.IsRetrieveMainDicomTags(ResourceType_Series) || | |
134 request.IsRetrieveMetadata(ResourceType_Series)) | |
135 { | |
136 return ResourceType_Series; | |
137 } | |
138 else | |
139 { | |
140 return ResourceType_Instance; | |
141 } | |
142 | |
143 default: | |
144 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
145 } | |
146 } | |
147 | |
148 | |
62 void GenericFind::ExecuteExpand(FindResponse& response, | 149 void GenericFind::ExecuteExpand(FindResponse& response, |
63 const FindRequest& request, | 150 const FindRequest& request, |
64 const std::string& identifier) | 151 const std::string& identifier) |
65 { | 152 { |
66 int64_t internalId; | 153 int64_t internalId; |
108 { | 195 { |
109 assert(!parent.empty()); | 196 assert(!parent.empty()); |
110 resource->SetParentIdentifier(parent); | 197 resource->SetParentIdentifier(parent); |
111 } | 198 } |
112 | 199 |
113 if (request.IsRetrieveMainDicomTags()) | 200 { |
114 { | 201 int64_t currentId = internalId; |
115 DicomMap m; | 202 ResourceType currentLevel = level; |
116 transaction_.GetMainDicomTags(m, internalId); | 203 const ResourceType topLevel = GetTopLevelOfInterest(request); |
117 | 204 |
118 DicomArray a(m); | 205 for (;;) |
119 for (size_t i = 0; i < a.GetSize(); i++) | 206 { |
120 { | 207 if (request.IsRetrieveMainDicomTags(currentLevel)) |
121 const DicomElement& element = a.GetElement(i); | 208 { |
122 if (element.GetValue().IsString()) | 209 RetrieveMainDicomTags(*resource, currentLevel, currentId); |
123 { | 210 } |
124 resource->AddStringDicomTag(element.GetTag().GetGroup(), element.GetTag().GetElement(), | 211 |
125 element.GetValue().GetContent()); | 212 if (request.IsRetrieveMetadata(currentLevel)) |
126 } | 213 { |
127 else | 214 transaction_.GetAllMetadata(resource->GetMetadata(currentLevel), currentId); |
128 { | 215 } |
129 throw OrthancException(ErrorCode_BadParameterType); | 216 |
130 } | 217 if (currentLevel == topLevel) |
131 } | 218 { |
132 } | 219 break; |
133 | 220 } |
134 if (request.IsRetrieveMetadata()) | 221 else |
135 { | 222 { |
136 transaction_.GetAllMetadata(resource->GetMetadata(), internalId); | 223 int64_t parentId; |
224 if (transaction_.LookupParent(parentId, currentId)) | |
225 { | |
226 currentId = parentId; | |
227 currentLevel = GetParentResourceType(currentLevel); | |
228 } | |
229 else | |
230 { | |
231 throw OrthancException(ErrorCode_DatabasePlugin); | |
232 } | |
233 } | |
234 } | |
137 } | 235 } |
138 | 236 |
139 if (request.IsRetrieveLabels()) | 237 if (request.IsRetrieveLabels()) |
140 { | 238 { |
141 transaction_.ListLabels(resource->GetLabels(), internalId); | 239 transaction_.ListLabels(resource->GetLabels(), internalId); |
167 std::list<std::string> children; | 265 std::list<std::string> children; |
168 transaction_.GetChildrenPublicId(children, internalId); | 266 transaction_.GetChildrenPublicId(children, internalId); |
169 | 267 |
170 for (std::list<std::string>::const_iterator it = children.begin(); it != children.end(); ++it) | 268 for (std::list<std::string>::const_iterator it = children.begin(); it != children.end(); ++it) |
171 { | 269 { |
172 resource->AddChildIdentifier(GetChildResourceType(level), *it); | 270 resource->AddChildIdentifier(*it); |
173 } | 271 } |
174 } | 272 } |
175 | 273 |
176 for (std::set<MetadataType>::const_iterator it = request.GetRetrieveChildrenMetadata().begin(); | 274 for (std::set<MetadataType>::const_iterator it = request.GetRetrieveChildrenMetadata().begin(); |
177 it != request.GetRetrieveChildrenMetadata().end(); ++it) | 275 it != request.GetRetrieveChildrenMetadata().end(); ++it) |
178 { | 276 { |
179 std::list<std::string> values; | 277 std::list<std::string> values; |
180 transaction_.GetChildrenMetadata(values, internalId, *it); | 278 transaction_.GetChildrenMetadata(values, internalId, *it); |
181 resource->AddChildrenMetadata(*it, values); | 279 resource->AddChildrenMetadata(*it, values); |
280 } | |
281 | |
282 if (!request.GetRetrieveAttachmentOfOneInstance().empty()) | |
283 { | |
284 std::set<FileContentType> todo = request.GetRetrieveAttachmentOfOneInstance(); | |
285 std::stack< std::pair<ResourceType, int64_t> > candidates; | |
286 candidates.push(std::make_pair(level, internalId)); | |
287 | |
288 while (!todo.empty() && | |
289 !candidates.empty()) | |
290 { | |
291 std::pair<ResourceType, int64_t> top = candidates.top(); | |
292 candidates.pop(); | |
293 | |
294 if (top.first == ResourceType_Instance) | |
295 { | |
296 std::set<FileContentType> nextTodo; | |
297 | |
298 for (std::set<FileContentType>::const_iterator it = todo.begin(); it != todo.end(); ++it) | |
299 { | |
300 FileInfo attachment; | |
301 int64_t revision; | |
302 if (transaction_.LookupAttachment(attachment, revision, top.second, *it)) | |
303 { | |
304 resource->AddAttachmentOfOneInstance(attachment); | |
305 } | |
306 else | |
307 { | |
308 nextTodo.insert(*it); | |
309 } | |
310 } | |
311 | |
312 todo = nextTodo; | |
313 } | |
314 else | |
315 { | |
316 std::list<int64_t> children; | |
317 transaction_.GetChildrenInternalId(children, top.second); | |
318 for (std::list<int64_t>::const_iterator it = children.begin(); it != children.end(); ++it) | |
319 { | |
320 candidates.push(std::make_pair(GetChildResourceType(top.first), *it)); | |
321 } | |
322 } | |
323 } | |
182 } | 324 } |
183 | 325 |
184 response.Add(resource.release()); | 326 response.Add(resource.release()); |
185 } | 327 } |
186 } | 328 } |