Mercurial > hg > orthanc
comparison OrthancServer/OrthancFindRequestHandler.cpp @ 608:0bedf8ff9288 find-move-scp
basic find scp
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 17 Oct 2013 18:07:55 +0200 |
parents | c931ac02db82 |
children | 5ba825b87b21 |
comparison
equal
deleted
inserted
replaced
606:ce5d2040c47b | 608:0bedf8ff9288 |
---|---|
30 **/ | 30 **/ |
31 | 31 |
32 #include "OrthancFindRequestHandler.h" | 32 #include "OrthancFindRequestHandler.h" |
33 | 33 |
34 #include <glog/logging.h> | 34 #include <glog/logging.h> |
35 #include <boost/regex.hpp> | |
35 | 36 |
36 #include "../Core/DicomFormat/DicomArray.h" | 37 #include "../Core/DicomFormat/DicomArray.h" |
38 #include "ServerToolbox.h" | |
37 | 39 |
38 namespace Orthanc | 40 namespace Orthanc |
39 { | 41 { |
42 static bool ApplyRangeConstraint(const std::string& value, | |
43 const std::string& constraint) | |
44 { | |
45 // TODO | |
46 return false; | |
47 } | |
48 | |
49 | |
50 static bool ApplyListConstraint(const std::string& value, | |
51 const std::string& constraint) | |
52 { | |
53 std::cout << value << std::endl; | |
54 | |
55 std::string v1 = value; | |
56 Toolbox::ToLowerCase(v1); | |
57 | |
58 std::vector<std::string> items; | |
59 Toolbox::TokenizeString(items, constraint, '\\'); | |
60 | |
61 for (size_t i = 0; i < items.size(); i++) | |
62 { | |
63 Toolbox::ToLowerCase(items[i]); | |
64 if (items[i] == v1) | |
65 { | |
66 return true; | |
67 } | |
68 } | |
69 | |
70 return false; | |
71 } | |
72 | |
73 | |
74 static bool Matches(const std::string& value, | |
75 const std::string& constraint) | |
76 { | |
77 // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained | |
78 // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html | |
79 | |
80 if (constraint.find('-') != std::string::npos) | |
81 { | |
82 return ApplyRangeConstraint(value, constraint); | |
83 } | |
84 | |
85 if (constraint.find('\\') != std::string::npos) | |
86 { | |
87 return ApplyListConstraint(value, constraint); | |
88 } | |
89 | |
90 if (constraint.find('*') != std::string::npos || | |
91 constraint.find('?') != std::string::npos) | |
92 { | |
93 // TODO - Cache the constructed regular expression | |
94 boost::regex pattern(Toolbox::WildcardToRegularExpression(constraint), | |
95 boost::regex::icase /* case insensitive search */); | |
96 return boost::regex_match(value, pattern); | |
97 } | |
98 else | |
99 { | |
100 std::string v1 = value; | |
101 std::string v2 = constraint; | |
102 | |
103 Toolbox::ToLowerCase(v1); | |
104 Toolbox::ToLowerCase(v2); | |
105 | |
106 return v1 == v2; | |
107 } | |
108 } | |
109 | |
110 | |
111 static bool LookupOneInstance(std::string& result, | |
112 ServerIndex& index, | |
113 const std::string& id, | |
114 ResourceType type) | |
115 { | |
116 if (type == ResourceType_Instance) | |
117 { | |
118 result = id; | |
119 return true; | |
120 } | |
121 | |
122 std::string childId; | |
123 | |
124 { | |
125 std::list<std::string> children; | |
126 index.GetChildInstances(children, id); | |
127 | |
128 if (children.size() == 0) | |
129 { | |
130 return false; | |
131 } | |
132 | |
133 childId = children.front(); | |
134 } | |
135 | |
136 return LookupOneInstance(result, index, childId, GetChildResourceType(type)); | |
137 } | |
138 | |
139 | |
140 static bool Matches(const Json::Value& resource, | |
141 const DicomArray& query) | |
142 { | |
143 for (size_t i = 0; i < query.GetSize(); i++) | |
144 { | |
145 if (query.GetElement(i).GetValue().IsNull() || | |
146 query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL || | |
147 query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET) | |
148 { | |
149 continue; | |
150 } | |
151 | |
152 std::string tag = query.GetElement(i).GetTag().Format(); | |
153 std::cout << tag << std::endl; | |
154 | |
155 std::string value; | |
156 if (resource.isMember(tag)) | |
157 { | |
158 value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); | |
159 } | |
160 | |
161 if (!Matches(value, query.GetElement(i).GetValue().AsString())) | |
162 { | |
163 return false; | |
164 } | |
165 } | |
166 | |
167 return true; | |
168 } | |
169 | |
170 | |
171 static void AddAnswer(DicomFindAnswers& answers, | |
172 const Json::Value& resource, | |
173 const DicomArray& query) | |
174 { | |
175 DicomMap result; | |
176 | |
177 for (size_t i = 0; i < query.GetSize(); i++) | |
178 { | |
179 if (query.GetElement(i).GetTag() != DICOM_TAG_QUERY_RETRIEVE_LEVEL && | |
180 query.GetElement(i).GetTag() != DICOM_TAG_SPECIFIC_CHARACTER_SET) | |
181 { | |
182 std::string tag = query.GetElement(i).GetTag().Format(); | |
183 std::string value; | |
184 if (resource.isMember(tag)) | |
185 { | |
186 value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); | |
187 result.SetValue(query.GetElement(i).GetTag(), value); | |
188 } | |
189 } | |
190 } | |
191 | |
192 answers.Add(result); | |
193 } | |
194 | |
195 | |
40 void OrthancFindRequestHandler::Handle(const DicomMap& input, | 196 void OrthancFindRequestHandler::Handle(const DicomMap& input, |
41 DicomFindAnswers& answers) | 197 DicomFindAnswers& answers) |
42 { | 198 { |
43 LOG(WARNING) << "Find-SCU request received"; | 199 LOG(WARNING) << "Find-SCU request received"; |
44 | 200 |
61 throw OrthancException(ErrorCode_NotImplemented); | 217 throw OrthancException(ErrorCode_NotImplemented); |
62 } | 218 } |
63 | 219 |
64 | 220 |
65 /** | 221 /** |
66 * Retrieve the constraints of the query. | 222 * Retrieve all the resources for this query level. |
67 **/ | 223 **/ |
68 | 224 |
225 Json::Value resources; | |
226 context_.GetIndex().GetAllUuids(resources, level); | |
227 assert(resources.type() == Json::arrayValue); | |
228 | |
229 | |
230 // TODO : Speed up using MainDicomTags (to avoid looping over ALL | |
231 // the resources and reading the JSON file for each of them) | |
232 | |
233 | |
234 /** | |
235 * Loop over all the resources for this query level. | |
236 **/ | |
237 | |
69 DicomArray query(input); | 238 DicomArray query(input); |
70 | 239 for (Json::Value::ArrayIndex i = 0; i < resources.size(); i++) |
71 DicomMap constraintsTmp; | 240 { |
72 DicomMap wildcardConstraintsTmp; | 241 try |
73 | 242 { |
74 for (size_t i = 0; i < query.GetSize(); i++) | 243 std::string instance; |
75 { | 244 if (LookupOneInstance(instance, context_.GetIndex(), resources[i].asString(), level)) |
76 if (!query.GetElement(i).GetValue().IsNull() && | |
77 query.GetElement(i).GetTag() != DICOM_TAG_QUERY_RETRIEVE_LEVEL && | |
78 query.GetElement(i).GetTag() != DICOM_TAG_SPECIFIC_CHARACTER_SET) | |
79 { | |
80 DicomTag tag = query.GetElement(i).GetTag(); | |
81 std::string value = query.GetElement(i).GetValue().AsString(); | |
82 | |
83 if (value.find('*') != std::string::npos || | |
84 value.find('?') != std::string::npos || | |
85 value.find('\\') != std::string::npos || | |
86 value.find('-') != std::string::npos) | |
87 { | 245 { |
88 wildcardConstraintsTmp.SetValue(tag, value); | 246 Json::Value resource; |
247 context_.ReadJson(resource, instance); | |
248 | |
249 if (Matches(resource, query)) | |
250 { | |
251 AddAnswer(answers, resource, query); | |
252 } | |
89 } | 253 } |
90 else | 254 } |
91 { | 255 catch (OrthancException&) |
92 constraintsTmp.SetValue(tag, value); | 256 { |
93 } | 257 // This resource has been deleted during the find request |
94 } | 258 } |
95 } | 259 } |
96 | |
97 DicomArray constraints(constraintsTmp); | |
98 DicomArray wildcardConstraints(wildcardConstraintsTmp); | |
99 | |
100 // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained | |
101 // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html | |
102 | |
103 constraints.Print(stdout); | |
104 printf("\n"); fflush(stdout); | |
105 wildcardConstraints.Print(stdout); | |
106 printf("\n"); fflush(stdout); | |
107 } | 260 } |
108 } | 261 } |