Mercurial > hg > orthanc
annotate Plugins/Samples/ModalityWorklists/Plugin.cpp @ 2140:aa4b8895cd23
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 09 Nov 2016 16:12:47 +0100 |
parents | 7a05144cb919 |
children | 395522e46b2b |
rev | line source |
---|---|
1802 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
1900 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
1802 | 4 * Department, University Hospital of Liege, Belgium |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 | |
21 #include <orthanc/OrthancCPlugin.h> | |
22 | |
23 #include <boost/filesystem.hpp> | |
24 #include <json/value.h> | |
25 #include <json/reader.h> | |
26 #include <string.h> | |
27 #include <iostream> | |
1814 | 28 #include <algorithm> |
1802 | 29 |
30 static OrthancPluginContext* context_ = NULL; | |
31 static std::string folder_; | |
32 | |
33 | |
34 static bool ReadFile(std::string& result, | |
35 const std::string& path) | |
36 { | |
37 OrthancPluginMemoryBuffer tmp; | |
38 if (OrthancPluginReadFile(context_, &tmp, path.c_str())) | |
39 { | |
40 return false; | |
41 } | |
42 else | |
43 { | |
44 result.assign(reinterpret_cast<const char*>(tmp.data), tmp.size); | |
45 OrthancPluginFreeMemoryBuffer(context_, &tmp); | |
46 return true; | |
47 } | |
48 } | |
49 | |
50 | |
51 /** | |
52 * This is the main function for matching a DICOM worklist against a query. | |
53 **/ | |
54 static OrthancPluginErrorCode MatchWorklist(OrthancPluginWorklistAnswers* answers, | |
55 const OrthancPluginWorklistQuery* query, | |
56 const std::string& path) | |
57 { | |
58 std::string dicom; | |
59 if (!ReadFile(dicom, path)) | |
60 { | |
61 // Cannot read this file, ignore this error | |
62 return OrthancPluginErrorCode_Success; | |
63 } | |
64 | |
1810
796d0b087fb8
more consistent naming in worklist primitives
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1808
diff
changeset
|
65 if (OrthancPluginWorklistIsMatch(context_, query, dicom.c_str(), dicom.size())) |
1802 | 66 { |
67 // This DICOM file matches the worklist query, add it to the answers | |
1810
796d0b087fb8
more consistent naming in worklist primitives
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1808
diff
changeset
|
68 return OrthancPluginWorklistAddAnswer |
1802 | 69 (context_, answers, query, dicom.c_str(), dicom.size()); |
70 } | |
71 else | |
72 { | |
73 // This DICOM file does not match | |
74 return OrthancPluginErrorCode_Success; | |
75 } | |
76 } | |
77 | |
78 | |
79 | |
80 static bool ConvertToJson(Json::Value& result, | |
81 char* content) | |
82 { | |
83 if (content == NULL) | |
84 { | |
85 return false; | |
86 } | |
87 else | |
88 { | |
89 Json::Reader reader; | |
90 bool success = reader.parse(content, content + strlen(content), result); | |
91 OrthancPluginFreeString(context_, content); | |
92 return success; | |
93 } | |
94 } | |
95 | |
96 | |
97 static bool GetQueryDicom(Json::Value& value, | |
98 const OrthancPluginWorklistQuery* query) | |
99 { | |
100 OrthancPluginMemoryBuffer dicom; | |
1810
796d0b087fb8
more consistent naming in worklist primitives
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1808
diff
changeset
|
101 if (OrthancPluginWorklistGetDicomQuery(context_, &dicom, query)) |
1802 | 102 { |
103 return false; | |
104 } | |
105 | |
106 char* json = OrthancPluginDicomBufferToJson(context_, reinterpret_cast<const char*>(dicom.data), | |
107 dicom.size, | |
108 OrthancPluginDicomToJsonFormat_Short, | |
109 static_cast<OrthancPluginDicomToJsonFlags>(0), 0); | |
110 OrthancPluginFreeMemoryBuffer(context_, &dicom); | |
111 | |
112 return ConvertToJson(value, json); | |
113 } | |
114 | |
115 | |
1814 | 116 static void ToLowerCase(std::string& s) |
117 { | |
118 std::transform(s.begin(), s.end(), s.begin(), tolower); | |
119 } | |
120 | |
121 | |
1802 | 122 OrthancPluginErrorCode Callback(OrthancPluginWorklistAnswers* answers, |
123 const OrthancPluginWorklistQuery* query, | |
124 const char* remoteAet, | |
125 const char* calledAet) | |
126 { | |
1911 | 127 namespace fs = boost::filesystem; |
128 | |
1802 | 129 Json::Value json; |
130 | |
131 if (!GetQueryDicom(json, query)) | |
132 { | |
133 return OrthancPluginErrorCode_InternalError; | |
134 } | |
135 | |
1890
74dc6b764ff0
Fix modality worklists lookups if tags with UN (unknown) VR are present
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1814
diff
changeset
|
136 { |
74dc6b764ff0
Fix modality worklists lookups if tags with UN (unknown) VR are present
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1814
diff
changeset
|
137 std::string msg = ("Received worklist query from remote modality " + |
74dc6b764ff0
Fix modality worklists lookups if tags with UN (unknown) VR are present
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1814
diff
changeset
|
138 std::string(remoteAet) + ":\n" + json.toStyledString()); |
74dc6b764ff0
Fix modality worklists lookups if tags with UN (unknown) VR are present
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1814
diff
changeset
|
139 OrthancPluginLogInfo(context_, msg.c_str()); |
74dc6b764ff0
Fix modality worklists lookups if tags with UN (unknown) VR are present
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1814
diff
changeset
|
140 } |
1802 | 141 |
1911 | 142 fs::path source(folder_); |
143 fs::directory_iterator end; | |
1802 | 144 |
145 try | |
146 { | |
1911 | 147 for (fs::directory_iterator it(source); it != end; ++it) |
1802 | 148 { |
1911 | 149 fs::file_type type(it->status().type()); |
150 | |
151 if (type == fs::regular_file || | |
152 type == fs::reparse_file) // cf. BitBucket issue #11 | |
1802 | 153 { |
1911 | 154 std::string extension = fs::extension(it->path()); |
1814 | 155 ToLowerCase(extension); |
156 | |
157 if (extension == ".wl") | |
1802 | 158 { |
159 OrthancPluginErrorCode error = MatchWorklist(answers, query, it->path().string()); | |
160 if (error) | |
161 { | |
162 OrthancPluginLogError(context_, "Error while adding an answer to a worklist request"); | |
163 return error; | |
164 } | |
165 } | |
166 } | |
167 } | |
168 } | |
1911 | 169 catch (fs::filesystem_error&) |
1802 | 170 { |
171 std::string description = std::string("Inexistent folder while scanning for worklists: ") + source.string(); | |
172 OrthancPluginLogError(context_, description.c_str()); | |
173 return OrthancPluginErrorCode_DirectoryExpected; | |
174 } | |
175 | |
176 // Uncomment the following line if too many answers are to be returned | |
177 // OrthancPluginMarkWorklistAnswersIncomplete(context_, answers); | |
178 | |
179 return OrthancPluginErrorCode_Success; | |
180 } | |
181 | |
182 | |
183 extern "C" | |
184 { | |
185 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c) | |
186 { | |
187 context_ = c; | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
188 OrthancPluginLogWarning(context_, "Sample worklist plugin is initializing"); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
189 OrthancPluginSetDescription(context_, "Serve DICOM modality worklists from a folder with Orthanc."); |
1802 | 190 |
191 /* Check the version of the Orthanc core */ | |
192 if (OrthancPluginCheckVersion(c) == 0) | |
193 { | |
194 char info[1024]; | |
195 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", | |
196 context_->orthancVersion, | |
197 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, | |
198 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, | |
199 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | |
200 OrthancPluginLogError(context_, info); | |
201 return -1; | |
202 } | |
203 | |
204 Json::Value configuration; | |
205 if (!ConvertToJson(configuration, OrthancPluginGetConfiguration(context_))) | |
206 { | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
207 OrthancPluginLogError(context_, "Cannot access the configuration of the worklist server"); |
1802 | 208 return -1; |
209 } | |
210 | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
211 bool enabled = false; |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
212 |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
213 if (configuration.isMember("Worklists")) |
1802 | 214 { |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
215 const Json::Value& config = configuration["Worklists"]; |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
216 if (!config.isMember("Enable") || |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
217 config["Enable"].type() != Json::booleanValue) |
1802 | 218 { |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
219 OrthancPluginLogError(context_, "The configuration option \"Worklists.Enable\" must contain a Boolean"); |
1802 | 220 return -1; |
221 } | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
222 else |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
223 { |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
224 enabled = config["Enable"].asBool(); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
225 if (enabled) |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
226 { |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
227 if (!config.isMember("Database") || |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
228 config["Database"].type() != Json::stringValue) |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
229 { |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
230 OrthancPluginLogError(context_, "The configuration option \"Worklists.Database\" must contain a path"); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
231 return -1; |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
232 } |
1802 | 233 |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
234 folder_ = config["Database"].asString(); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
235 } |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
236 else |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
237 { |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
238 OrthancPluginLogWarning(context_, "Worklists server is disabled by the configuration file"); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
239 } |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
240 } |
1802 | 241 } |
242 else | |
243 { | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
244 OrthancPluginLogWarning(context_, "Worklists server is disabled, no suitable configuration section was provided"); |
1802 | 245 } |
246 | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
247 if (enabled) |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
248 { |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
249 std::string message = "The database of worklists will be read from folder: " + folder_; |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
250 OrthancPluginLogWarning(context_, message.c_str()); |
1802 | 251 |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
252 OrthancPluginRegisterWorklistCallback(context_, Callback); |
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
253 } |
1802 | 254 |
255 return 0; | |
256 } | |
257 | |
258 | |
259 ORTHANC_PLUGINS_API void OrthancPluginFinalize() | |
260 { | |
261 OrthancPluginLogWarning(context_, "Sample worklist plugin is finalizing"); | |
262 } | |
263 | |
264 | |
265 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() | |
266 { | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
267 return "worklists"; |
1802 | 268 } |
269 | |
270 | |
271 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() | |
272 { | |
1808
9c2ffc4e938b
configuration of the sample modality worklists plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1802
diff
changeset
|
273 return MODALITY_WORKLISTS_VERSION; |
1802 | 274 } |
275 } |