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 }