Mercurial > hg > orthanc
annotate OrthancServer/OrthancFindRequestHandler.cpp @ 612:fdd5f7f9c4d7 find-move-scp
refactoring
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 18 Oct 2013 14:17:51 +0200 |
parents | 9924aec1d694 |
children | ec0b7a51d7bd |
rev | line source |
---|---|
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
1 /** |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
2 * Orthanc - A Lightweight, RESTful DICOM Store |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
3 * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
4 * Belgium |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
5 * |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
6 * This program is free software: you can redistribute it and/or |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
7 * modify it under the terms of the GNU General Public License as |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
8 * published by the Free Software Foundation, either version 3 of the |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
9 * License, or (at your option) any later version. |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
10 * |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
11 * In addition, as a special exception, the copyright holders of this |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
12 * program give permission to link the code of its release with the |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
14 * that use the same license as the "OpenSSL" library), and distribute |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
15 * the linked executables. You must obey the GNU General Public License |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
16 * in all respects for all of the code used other than "OpenSSL". If you |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
17 * modify file(s) with this exception, you may extend this exception to |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
18 * your version of the file(s), but you are not obligated to do so. If |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
19 * you do not wish to do so, delete this exception statement from your |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
20 * version. If you delete this exception statement from all source files |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
21 * in the program, then also delete it here. |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
22 * |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
23 * This program is distributed in the hope that it will be useful, but |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
24 * WITHOUT ANY WARRANTY; without even the implied warranty of |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
26 * General Public License for more details. |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
27 * |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
28 * You should have received a copy of the GNU General Public License |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
30 **/ |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
31 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
32 #include "OrthancFindRequestHandler.h" |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
33 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
34 #include <glog/logging.h> |
608 | 35 #include <boost/regex.hpp> |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
36 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
37 #include "../Core/DicomFormat/DicomArray.h" |
608 | 38 #include "ServerToolbox.h" |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
39 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
40 namespace Orthanc |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
41 { |
610 | 42 static std::string ToLowerCase(const std::string& s) |
43 { | |
44 std::string result = s; | |
45 Toolbox::ToLowerCase(result); | |
46 return result; | |
47 } | |
48 | |
608 | 49 static bool ApplyRangeConstraint(const std::string& value, |
50 const std::string& constraint) | |
51 { | |
610 | 52 size_t separator = constraint.find('-'); |
53 std::string lower = ToLowerCase(constraint.substr(0, separator)); | |
54 std::string upper = ToLowerCase(constraint.substr(separator + 1)); | |
55 std::string v = ToLowerCase(value); | |
56 | |
57 if (lower.size() == 0 && upper.size() == 0) | |
58 { | |
59 return false; | |
60 } | |
61 | |
62 if (lower.size() == 0) | |
63 { | |
64 return v <= upper; | |
65 } | |
66 | |
67 if (upper.size() == 0) | |
68 { | |
69 return v >= lower; | |
70 } | |
71 | |
72 return (v >= lower && v <= upper); | |
608 | 73 } |
74 | |
75 | |
76 static bool ApplyListConstraint(const std::string& value, | |
77 const std::string& constraint) | |
78 { | |
610 | 79 std::string v1 = ToLowerCase(value); |
608 | 80 |
81 std::vector<std::string> items; | |
82 Toolbox::TokenizeString(items, constraint, '\\'); | |
83 | |
84 for (size_t i = 0; i < items.size(); i++) | |
85 { | |
86 Toolbox::ToLowerCase(items[i]); | |
87 if (items[i] == v1) | |
88 { | |
89 return true; | |
90 } | |
91 } | |
92 | |
93 return false; | |
94 } | |
95 | |
96 | |
97 static bool Matches(const std::string& value, | |
98 const std::string& constraint) | |
99 { | |
100 // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained | |
101 // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html | |
102 | |
103 if (constraint.find('-') != std::string::npos) | |
104 { | |
105 return ApplyRangeConstraint(value, constraint); | |
106 } | |
107 | |
108 if (constraint.find('\\') != std::string::npos) | |
109 { | |
110 return ApplyListConstraint(value, constraint); | |
111 } | |
112 | |
113 if (constraint.find('*') != std::string::npos || | |
114 constraint.find('?') != std::string::npos) | |
115 { | |
116 // TODO - Cache the constructed regular expression | |
117 boost::regex pattern(Toolbox::WildcardToRegularExpression(constraint), | |
118 boost::regex::icase /* case insensitive search */); | |
119 return boost::regex_match(value, pattern); | |
120 } | |
121 else | |
122 { | |
610 | 123 return ToLowerCase(value) == ToLowerCase(constraint); |
608 | 124 } |
125 } | |
126 | |
127 | |
128 static bool LookupOneInstance(std::string& result, | |
129 ServerIndex& index, | |
130 const std::string& id, | |
131 ResourceType type) | |
132 { | |
133 if (type == ResourceType_Instance) | |
134 { | |
135 result = id; | |
136 return true; | |
137 } | |
138 | |
139 std::string childId; | |
140 | |
141 { | |
142 std::list<std::string> children; | |
143 index.GetChildInstances(children, id); | |
144 | |
145 if (children.size() == 0) | |
146 { | |
147 return false; | |
148 } | |
149 | |
150 childId = children.front(); | |
151 } | |
152 | |
153 return LookupOneInstance(result, index, childId, GetChildResourceType(type)); | |
154 } | |
155 | |
156 | |
157 static bool Matches(const Json::Value& resource, | |
158 const DicomArray& query) | |
159 { | |
160 for (size_t i = 0; i < query.GetSize(); i++) | |
161 { | |
162 if (query.GetElement(i).GetValue().IsNull() || | |
163 query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL || | |
611
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
164 query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET || |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
165 query.GetElement(i).GetTag() == DICOM_TAG_MODALITIES_IN_STUDY) |
608 | 166 { |
167 continue; | |
168 } | |
169 | |
170 std::string tag = query.GetElement(i).GetTag().Format(); | |
171 std::string value; | |
172 if (resource.isMember(tag)) | |
173 { | |
174 value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); | |
175 } | |
176 | |
177 if (!Matches(value, query.GetElement(i).GetValue().AsString())) | |
178 { | |
179 return false; | |
180 } | |
181 } | |
182 | |
183 return true; | |
184 } | |
185 | |
186 | |
187 static void AddAnswer(DicomFindAnswers& answers, | |
188 const Json::Value& resource, | |
189 const DicomArray& query) | |
190 { | |
191 DicomMap result; | |
192 | |
193 for (size_t i = 0; i < query.GetSize(); i++) | |
194 { | |
195 if (query.GetElement(i).GetTag() != DICOM_TAG_QUERY_RETRIEVE_LEVEL && | |
196 query.GetElement(i).GetTag() != DICOM_TAG_SPECIFIC_CHARACTER_SET) | |
197 { | |
198 std::string tag = query.GetElement(i).GetTag().Format(); | |
199 std::string value; | |
200 if (resource.isMember(tag)) | |
201 { | |
202 value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); | |
203 result.SetValue(query.GetElement(i).GetTag(), value); | |
204 } | |
205 } | |
206 } | |
207 | |
208 answers.Add(result); | |
209 } | |
210 | |
211 | |
612 | 212 static bool ApplyModalitiesInStudyFilter(Json::Value& filteredStudies, |
213 const Json::Value& studies, | |
214 const DicomMap& input, | |
215 ServerIndex& index) | |
216 { | |
217 filteredStudies = Json::arrayValue; | |
218 | |
219 const DicomValue& v = input.GetValue(DICOM_TAG_MODALITIES_IN_STUDY); | |
220 if (v.IsNull()) | |
221 { | |
222 return false; | |
223 } | |
224 | |
225 // Move the allowed modalities into a "std::set" | |
226 std::vector<std::string> tmp; | |
227 Toolbox::TokenizeString(tmp, v.AsString(), '\\'); | |
228 | |
229 std::set<std::string> modalities; | |
230 for (size_t i = 0; i < tmp.size(); i++) | |
231 { | |
232 modalities.insert(tmp[i]); | |
233 } | |
234 | |
235 // Loop over the studies | |
236 for (Json::Value::ArrayIndex i = 0; i < studies.size(); i++) | |
237 { | |
238 try | |
239 { | |
240 // We are considering a single study. Check whether one of | |
241 // its child series matches one of the modalities. | |
242 Json::Value study; | |
243 if (index.LookupResource(study, studies[i].asString(), ResourceType_Study)) | |
244 { | |
245 // Loop over the series of the considered study. | |
246 for (Json::Value::ArrayIndex j = 0; j < study["Series"].size(); j++) // (*) | |
247 { | |
248 Json::Value series; | |
249 if (index.LookupResource(series, study["Series"][j].asString(), ResourceType_Series)) | |
250 { | |
251 // Get the modality of this series | |
252 if (series["MainDicomTags"].isMember("Modality")) | |
253 { | |
254 std::string modality = series["MainDicomTags"]["Modality"].asString(); | |
255 if (modalities.find(modality) != modalities.end()) | |
256 { | |
257 // This series of the considered study matches one | |
258 // of the required modalities. Take the study into | |
259 // consideration for future filtering. | |
260 filteredStudies.append(studies[i]); | |
261 | |
262 // We have finished considering this study. Break the study loop at (*). | |
263 break; | |
264 } | |
265 } | |
266 } | |
267 } | |
268 } | |
269 } | |
270 catch (OrthancException&) | |
271 { | |
272 // This resource has probably been deleted during the find request | |
273 } | |
274 } | |
275 | |
276 return true; | |
277 } | |
278 | |
279 | |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
280 void OrthancFindRequestHandler::Handle(const DicomMap& input, |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
281 DicomFindAnswers& answers) |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
282 { |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
283 LOG(WARNING) << "Find-SCU request received"; |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
284 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
285 /** |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
286 * Retrieve the query level. |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
287 **/ |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
288 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
289 const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL); |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
290 if (levelTmp == NULL) |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
291 { |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
292 throw OrthancException(ErrorCode_BadRequest); |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
293 } |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
294 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
295 ResourceType level = StringToResourceType(levelTmp->AsString().c_str()); |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
296 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
297 if (level != ResourceType_Patient && |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
298 level != ResourceType_Study && |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
299 level != ResourceType_Series) |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
300 { |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
301 throw OrthancException(ErrorCode_NotImplemented); |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
302 } |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
303 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
304 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
305 /** |
608 | 306 * Retrieve all the resources for this query level. |
307 **/ | |
308 | |
309 Json::Value resources; | |
310 context_.GetIndex().GetAllUuids(resources, level); | |
311 assert(resources.type() == Json::arrayValue); | |
312 | |
313 // TODO : Speed up using MainDicomTags (to avoid looping over ALL | |
314 // the resources and reading the JSON file for each of them) | |
315 | |
316 | |
611
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
317 |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
318 /** |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
319 * Apply filtering on modalities for studies, if asked (this is an |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
320 * extension to standard DICOM) |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
321 * http://www.medicalconnections.co.uk/kb/Filtering_on_and_Retrieving_the_Modality_in_a_C_FIND |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
322 **/ |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
323 |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
324 if (level == ResourceType_Study && |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
325 input.HasTag(DICOM_TAG_MODALITIES_IN_STUDY)) |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
326 { |
612 | 327 Json::Value filtered; |
328 if (ApplyModalitiesInStudyFilter(filtered, resources, input, context_.GetIndex())) | |
611
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
329 { |
612 | 330 resources = filtered; |
611
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
331 } |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
332 } |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
333 |
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
334 |
608 | 335 /** |
336 * Loop over all the resources for this query level. | |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
337 **/ |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
338 |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
339 DicomArray query(input); |
608 | 340 for (Json::Value::ArrayIndex i = 0; i < resources.size(); i++) |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
341 { |
608 | 342 try |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
343 { |
608 | 344 std::string instance; |
345 if (LookupOneInstance(instance, context_.GetIndex(), resources[i].asString(), level)) | |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
346 { |
608 | 347 Json::Value resource; |
348 context_.ReadJson(resource, instance); | |
349 | |
350 if (Matches(resource, query)) | |
351 { | |
352 AddAnswer(answers, resource, query); | |
353 } | |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
354 } |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
355 } |
608 | 356 catch (OrthancException&) |
357 { | |
611
9924aec1d694
filtering on modalities
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
610
diff
changeset
|
358 // This resource has probably been deleted during the find request |
608 | 359 } |
565
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
360 } |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
361 } |
c931ac02db82
refactoring of find class
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff
changeset
|
362 } |