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 }