comparison OrthancServer/OrthancFindRequestHandler.cpp @ 1759:e268412adcf1 db-changes

removal of old implementation of search
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Oct 2015 12:59:18 +0100
parents 318c2e83c2bd
children 4f01c9d73f02
comparison
equal deleted inserted replaced
1758:318c2e83c2bd 1759:e268412adcf1
28 * You should have received a copy of the GNU General Public License 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/>. 29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 **/ 30 **/
31 31
32 32
33 #define USE_LOOKUP_RESOURCE 1
34
35
36
37 #include "PrecompiledHeadersServer.h" 33 #include "PrecompiledHeadersServer.h"
38 #include "OrthancFindRequestHandler.h" 34 #include "OrthancFindRequestHandler.h"
39 35
36 #include "../Core/DicomFormat/DicomArray.h"
40 #include "../Core/Logging.h" 37 #include "../Core/Logging.h"
41 #include "../Core/DicomFormat/DicomArray.h" 38 #include "FromDcmtkBridge.h"
39 #include "OrthancInitialization.h"
40 #include "Search/LookupResource.h"
42 #include "ServerToolbox.h" 41 #include "ServerToolbox.h"
43 #include "OrthancInitialization.h"
44 #include "FromDcmtkBridge.h"
45
46 #include "ResourceFinder.h"
47 #include "DicomFindQuery.h"
48 #include "Search/LookupResource.h"
49 42
50 #include <boost/regex.hpp> 43 #include <boost/regex.hpp>
51 44
52 45
53 namespace Orthanc 46 namespace Orthanc
93 answers.Add(result); 86 answers.Add(result);
94 } 87 }
95 } 88 }
96 89
97 90
98 namespace
99 {
100 class CFindQuery : public DicomFindQuery
101 {
102 private:
103 DicomFindAnswers& answers_;
104 ServerIndex& index_;
105 const DicomArray& query_;
106 bool hasModalitiesInStudy_;
107 std::set<std::string> modalitiesInStudy_;
108
109 public:
110 CFindQuery(DicomFindAnswers& answers,
111 ServerIndex& index,
112 const DicomArray& query) :
113 answers_(answers),
114 index_(index),
115 query_(query),
116 hasModalitiesInStudy_(false)
117 {
118 }
119
120 void SetModalitiesInStudy(const std::string& value)
121 {
122 hasModalitiesInStudy_ = true;
123
124 std::vector<std::string> tmp;
125 Toolbox::TokenizeString(tmp, value, '\\');
126
127 for (size_t i = 0; i < tmp.size(); i++)
128 {
129 modalitiesInStudy_.insert(tmp[i]);
130 }
131 }
132
133 virtual bool HasMainDicomTagsFilter(ResourceType level) const
134 {
135 if (DicomFindQuery::HasMainDicomTagsFilter(level))
136 {
137 return true;
138 }
139
140 return (level == ResourceType_Study &&
141 hasModalitiesInStudy_);
142 }
143
144 virtual bool FilterMainDicomTags(const std::string& resourceId,
145 ResourceType level,
146 const DicomMap& mainTags) const
147 {
148 if (!DicomFindQuery::FilterMainDicomTags(resourceId, level, mainTags))
149 {
150 return false;
151 }
152
153 if (level != ResourceType_Study ||
154 !hasModalitiesInStudy_)
155 {
156 return true;
157 }
158
159 try
160 {
161 // We are considering a single study, and the
162 // "MODALITIES_IN_STUDY" tag is set in the C-Find. Check
163 // whether one of its child series matches one of the
164 // modalities.
165
166 Json::Value study;
167 if (index_.LookupResource(study, resourceId, ResourceType_Study))
168 {
169 // Loop over the series of the considered study.
170 for (Json::Value::ArrayIndex j = 0; j < study["Series"].size(); j++)
171 {
172 Json::Value series;
173 if (index_.LookupResource(series, study["Series"][j].asString(), ResourceType_Series))
174 {
175 // Get the modality of this series
176 if (series["MainDicomTags"].isMember("Modality"))
177 {
178 std::string modality = series["MainDicomTags"]["Modality"].asString();
179 if (modalitiesInStudy_.find(modality) != modalitiesInStudy_.end())
180 {
181 // This series of the considered study matches one
182 // of the required modalities. Take the study into
183 // consideration for future filtering.
184 return true;
185 }
186 }
187 }
188 }
189 }
190 }
191 catch (OrthancException&)
192 {
193 // This resource has probably been deleted during the find request
194 }
195
196 return false;
197 }
198
199 virtual bool HasInstanceFilter() const
200 {
201 return true;
202 }
203
204 virtual bool FilterInstance(const std::string& instanceId,
205 const Json::Value& content) const
206 {
207 bool ok = DicomFindQuery::FilterInstance(instanceId, content);
208
209 if (ok)
210 {
211 // Add this resource to the answers
212 AddAnswer(answers_, content, query_);
213 }
214
215 return ok;
216 }
217 };
218 }
219
220
221
222 bool OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, 91 bool OrthancFindRequestHandler::Handle(DicomFindAnswers& answers,
223 const DicomMap& input, 92 const DicomMap& input,
224 const std::string& remoteIp, 93 const std::string& remoteIp,
225 const std::string& remoteAet) 94 const std::string& remoteAet)
226 { 95 {
279 148
280 /** 149 /**
281 * Build up the query object. 150 * Build up the query object.
282 **/ 151 **/
283 152
284 #if USE_LOOKUP_RESOURCE == 1
285 LookupResource finder(level); 153 LookupResource finder(level);
286 #else 154
287 CFindQuery findQuery(answers, context_.GetIndex(), query);
288 findQuery.SetLevel(level);
289 #endif
290
291 for (size_t i = 0; i < query.GetSize(); i++) 155 for (size_t i = 0; i < query.GetSize(); i++)
292 { 156 {
293 const DicomTag tag = query.GetElement(i).GetTag(); 157 const DicomTag tag = query.GetElement(i).GetTag();
294 158
295 if (query.GetElement(i).GetValue().IsNull() || 159 if (query.GetElement(i).GetValue().IsNull() ||
304 { 168 {
305 // An empty string corresponds to a "*" wildcard constraint, so we ignore it 169 // An empty string corresponds to a "*" wildcard constraint, so we ignore it
306 continue; 170 continue;
307 } 171 }
308 172
309 #if USE_LOOKUP_RESOURCE == 1
310
311 ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag); 173 ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag);
312 174
175 // DICOM specifies that searches must be case sensitive, except
176 // for tags with a PN value representation
313 bool sensitive = true; 177 bool sensitive = true;
314 if (vr == ValueRepresentation_PatientName) 178 if (vr == ValueRepresentation_PatientName)
315 { 179 {
316 sensitive = caseSensitivePN; 180 sensitive = caseSensitivePN;
317 } 181 }
318 182
319 finder.AddDicomConstraint(tag, value, sensitive); 183 finder.AddDicomConstraint(tag, value, sensitive);
320 #else
321
322 if (tag == DICOM_TAG_MODALITIES_IN_STUDY)
323 {
324 findQuery.SetModalitiesInStudy(value);
325 }
326 else
327 {
328 findQuery.SetConstraint(tag, value, caseSensitivePN);
329 }
330 #endif
331 } 184 }
332 185
333 186
334 /** 187 /**
335 * Run the query. 188 * Run the query.
336 **/ 189 **/
337 190
338 #if USE_LOOKUP_RESOURCE != 1
339 ResourceFinder finder(context_);
340
341 switch (level)
342 {
343 case ResourceType_Patient:
344 case ResourceType_Study:
345 case ResourceType_Series:
346 finder.SetMaxResults(maxResults_);
347 break;
348
349 case ResourceType_Instance:
350 finder.SetMaxResults(maxInstances_);
351 break;
352
353 default:
354 throw OrthancException(ErrorCode_InternalError);
355 }
356 #else
357 size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; 191 size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_;
358 192
359 #endif
360
361 #if USE_LOOKUP_RESOURCE == 1
362 std::vector<std::string> resources, instances; 193 std::vector<std::string> resources, instances;
363 context_.GetIndex().FindCandidates(resources, instances, finder); 194 context_.GetIndex().FindCandidates(resources, instances, finder);
364 195
365 assert(resources.size() == instances.size()); 196 assert(resources.size() == instances.size());
366 bool finished = true; 197 bool finished = true;
383 AddAnswer(answers, dicom, query); 214 AddAnswer(answers, dicom, query);
384 } 215 }
385 } 216 }
386 } 217 }
387 218
388 #else
389 std::list<std::string> tmp;
390 bool finished = finder.Apply(tmp, findQuery);
391 #endif
392
393 LOG(INFO) << "Number of matching resources: " << answers.GetSize(); 219 LOG(INFO) << "Number of matching resources: " << answers.GetSize();
394 220
395 return finished; 221 return finished;
396 } 222 }
397 } 223 }