Mercurial > hg > orthanc
comparison Plugins/Samples/ModalityWorklists/Plugin.cpp @ 2205:395522e46b2b
refactoring of the worklist sample using OrthancPluginCppWrapper
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 08 Dec 2016 16:16:25 +0100 |
parents | 7a05144cb919 |
children | 27106f7e3759 |
comparison
equal
deleted
inserted
replaced
2204:0158f2de8cad | 2205:395522e46b2b |
---|---|
16 * You should have received a copy of the GNU General Public License | 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/>. | 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 **/ | 18 **/ |
19 | 19 |
20 | 20 |
21 #include <orthanc/OrthancCPlugin.h> | 21 #include "../Common/OrthancPluginCppWrapper.h" |
22 | 22 |
23 #include <boost/filesystem.hpp> | 23 #include <boost/filesystem.hpp> |
24 #include <json/value.h> | 24 #include <json/value.h> |
25 #include <json/reader.h> | 25 #include <json/reader.h> |
26 #include <string.h> | 26 #include <string.h> |
29 | 29 |
30 static OrthancPluginContext* context_ = NULL; | 30 static OrthancPluginContext* context_ = NULL; |
31 static std::string folder_; | 31 static std::string folder_; |
32 | 32 |
33 | 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 /** | 34 /** |
52 * This is the main function for matching a DICOM worklist against a query. | 35 * This is the main function for matching a DICOM worklist against a query. |
53 **/ | 36 **/ |
54 static OrthancPluginErrorCode MatchWorklist(OrthancPluginWorklistAnswers* answers, | 37 static OrthancPluginErrorCode MatchWorklist(OrthancPluginWorklistAnswers* answers, |
55 const OrthancPluginWorklistQuery* query, | 38 const OrthancPluginWorklistQuery* query, |
56 const std::string& path) | 39 const std::string& path) |
57 { | 40 { |
58 std::string dicom; | 41 OrthancPlugins::MemoryBuffer dicom(context_); |
59 if (!ReadFile(dicom, path)) | 42 dicom.ReadFile(path); |
60 { | 43 |
61 // Cannot read this file, ignore this error | 44 if (OrthancPluginWorklistIsMatch(context_, query, dicom.GetData(), dicom.GetSize())) |
62 return OrthancPluginErrorCode_Success; | |
63 } | |
64 | |
65 if (OrthancPluginWorklistIsMatch(context_, query, dicom.c_str(), dicom.size())) | |
66 { | 45 { |
67 // This DICOM file matches the worklist query, add it to the answers | 46 // This DICOM file matches the worklist query, add it to the answers |
68 return OrthancPluginWorklistAddAnswer | 47 return OrthancPluginWorklistAddAnswer |
69 (context_, answers, query, dicom.c_str(), dicom.size()); | 48 (context_, answers, query, dicom.GetData(), dicom.GetSize()); |
70 } | 49 } |
71 else | 50 else |
72 { | 51 { |
73 // This DICOM file does not match | 52 // This DICOM file does not match |
74 return OrthancPluginErrorCode_Success; | 53 return OrthancPluginErrorCode_Success; |
75 } | 54 } |
76 } | 55 } |
77 | 56 |
78 | 57 |
79 | 58 |
80 static bool ConvertToJson(Json::Value& result, | 59 static void GetQueryDicom(Json::Value& value, |
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) | 60 const OrthancPluginWorklistQuery* query) |
99 { | 61 { |
100 OrthancPluginMemoryBuffer dicom; | 62 OrthancPlugins::MemoryBuffer dicom(context_); |
101 if (OrthancPluginWorklistGetDicomQuery(context_, &dicom, query)) | 63 dicom.GetDicomQuery(query); |
102 { | 64 |
103 return false; | 65 OrthancPlugins::OrthancString str(context_); |
104 } | 66 str.DicomToJson(dicom, OrthancPluginDicomToJsonFormat_Short, |
105 | 67 static_cast<OrthancPluginDicomToJsonFlags>(0), 0); |
106 char* json = OrthancPluginDicomBufferToJson(context_, reinterpret_cast<const char*>(dicom.data), | 68 |
107 dicom.size, | 69 str.ToJson(value); |
108 OrthancPluginDicomToJsonFormat_Short, | 70 } |
109 static_cast<OrthancPluginDicomToJsonFlags>(0), 0); | 71 |
110 OrthancPluginFreeMemoryBuffer(context_, &dicom); | |
111 | |
112 return ConvertToJson(value, json); | |
113 } | |
114 | |
115 | 72 |
116 static void ToLowerCase(std::string& s) | 73 static void ToLowerCase(std::string& s) |
117 { | 74 { |
118 std::transform(s.begin(), s.end(), s.begin(), tolower); | 75 std::transform(s.begin(), s.end(), s.begin(), tolower); |
119 } | 76 } |
122 OrthancPluginErrorCode Callback(OrthancPluginWorklistAnswers* answers, | 79 OrthancPluginErrorCode Callback(OrthancPluginWorklistAnswers* answers, |
123 const OrthancPluginWorklistQuery* query, | 80 const OrthancPluginWorklistQuery* query, |
124 const char* remoteAet, | 81 const char* remoteAet, |
125 const char* calledAet) | 82 const char* calledAet) |
126 { | 83 { |
127 namespace fs = boost::filesystem; | |
128 | |
129 Json::Value json; | |
130 | |
131 if (!GetQueryDicom(json, query)) | |
132 { | |
133 return OrthancPluginErrorCode_InternalError; | |
134 } | |
135 | |
136 { | |
137 std::string msg = ("Received worklist query from remote modality " + | |
138 std::string(remoteAet) + ":\n" + json.toStyledString()); | |
139 OrthancPluginLogInfo(context_, msg.c_str()); | |
140 } | |
141 | |
142 fs::path source(folder_); | |
143 fs::directory_iterator end; | |
144 | |
145 try | 84 try |
146 { | 85 { |
147 for (fs::directory_iterator it(source); it != end; ++it) | 86 namespace fs = boost::filesystem; |
148 { | 87 |
149 fs::file_type type(it->status().type()); | 88 { |
150 | 89 Json::Value json; |
151 if (type == fs::regular_file || | 90 GetQueryDicom(json, query); |
152 type == fs::reparse_file) // cf. BitBucket issue #11 | 91 |
92 std::string msg = ("Received worklist query from remote modality " + | |
93 std::string(remoteAet) + ":\n" + json.toStyledString()); | |
94 OrthancPluginLogInfo(context_, msg.c_str()); | |
95 } | |
96 | |
97 fs::path source(folder_); | |
98 fs::directory_iterator end; | |
99 | |
100 try | |
101 { | |
102 for (fs::directory_iterator it(source); it != end; ++it) | |
153 { | 103 { |
154 std::string extension = fs::extension(it->path()); | 104 fs::file_type type(it->status().type()); |
155 ToLowerCase(extension); | 105 |
156 | 106 if (type == fs::regular_file || |
157 if (extension == ".wl") | 107 type == fs::reparse_file) // cf. BitBucket issue #11 |
158 { | 108 { |
159 OrthancPluginErrorCode error = MatchWorklist(answers, query, it->path().string()); | 109 std::string extension = fs::extension(it->path()); |
160 if (error) | 110 ToLowerCase(extension); |
111 | |
112 if (extension == ".wl") | |
161 { | 113 { |
162 OrthancPluginLogError(context_, "Error while adding an answer to a worklist request"); | 114 OrthancPluginErrorCode error = MatchWorklist(answers, query, it->path().string()); |
163 return error; | 115 if (error) |
116 { | |
117 OrthancPluginLogError(context_, "Error while adding an answer to a worklist request"); | |
118 return error; | |
119 } | |
164 } | 120 } |
165 } | 121 } |
166 } | 122 } |
167 } | 123 } |
168 } | 124 catch (fs::filesystem_error&) |
169 catch (fs::filesystem_error&) | 125 { |
170 { | 126 std::string description = std::string("Inexistent folder while scanning for worklists: ") + source.string(); |
171 std::string description = std::string("Inexistent folder while scanning for worklists: ") + source.string(); | 127 OrthancPluginLogError(context_, description.c_str()); |
172 OrthancPluginLogError(context_, description.c_str()); | 128 return OrthancPluginErrorCode_DirectoryExpected; |
173 return OrthancPluginErrorCode_DirectoryExpected; | 129 } |
174 } | 130 |
175 | 131 // Uncomment the following line if too many answers are to be returned |
176 // Uncomment the following line if too many answers are to be returned | 132 // OrthancPluginMarkWorklistAnswersIncomplete(context_, answers); |
177 // OrthancPluginMarkWorklistAnswersIncomplete(context_, answers); | 133 |
178 | 134 return OrthancPluginErrorCode_Success; |
179 return OrthancPluginErrorCode_Success; | 135 } |
136 catch (OrthancPlugins::PluginException& e) | |
137 { | |
138 return e.GetErrorCode(); | |
139 } | |
180 } | 140 } |
181 | 141 |
182 | 142 |
183 extern "C" | 143 extern "C" |
184 { | 144 { |
185 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c) | 145 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c) |
186 { | 146 { |
187 context_ = c; | 147 context_ = c; |
188 OrthancPluginLogWarning(context_, "Sample worklist plugin is initializing"); | |
189 OrthancPluginSetDescription(context_, "Serve DICOM modality worklists from a folder with Orthanc."); | |
190 | 148 |
191 /* Check the version of the Orthanc core */ | 149 /* Check the version of the Orthanc core */ |
192 if (OrthancPluginCheckVersion(c) == 0) | 150 if (OrthancPluginCheckVersion(c) == 0) |
193 { | 151 { |
194 char info[1024]; | 152 char info[1024]; |
199 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | 157 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); |
200 OrthancPluginLogError(context_, info); | 158 OrthancPluginLogError(context_, info); |
201 return -1; | 159 return -1; |
202 } | 160 } |
203 | 161 |
204 Json::Value configuration; | 162 OrthancPlugins::LogWarning(context_, "Sample worklist plugin is initializing"); |
205 if (!ConvertToJson(configuration, OrthancPluginGetConfiguration(context_))) | 163 OrthancPluginSetDescription(context_, "Serve DICOM modality worklists from a folder with Orthanc."); |
206 { | 164 |
207 OrthancPluginLogError(context_, "Cannot access the configuration of the worklist server"); | 165 OrthancPlugins::OrthancConfiguration configuration(context_); |
208 return -1; | 166 |
209 } | 167 OrthancPlugins::OrthancConfiguration worklists; |
210 | 168 configuration.GetSection(worklists, "Worklists"); |
211 bool enabled = false; | 169 |
212 | 170 bool enabled = worklists.GetBooleanValue("Enable", false); |
213 if (configuration.isMember("Worklists")) | 171 if (enabled) |
214 { | 172 { |
215 const Json::Value& config = configuration["Worklists"]; | 173 if (worklists.LookupStringValue(folder_, "Database")) |
216 if (!config.isMember("Enable") || | |
217 config["Enable"].type() != Json::booleanValue) | |
218 { | 174 { |
219 OrthancPluginLogError(context_, "The configuration option \"Worklists.Enable\" must contain a Boolean"); | 175 OrthancPlugins::LogWarning(context_, "The database of worklists will be read from folder: " + folder_); |
220 return -1; | 176 OrthancPluginRegisterWorklistCallback(context_, Callback); |
221 } | 177 } |
222 else | 178 else |
223 { | 179 { |
224 enabled = config["Enable"].asBool(); | 180 OrthancPlugins::LogError(context_, "The configuration option \"Worklists.Database\" must contain a path"); |
225 if (enabled) | 181 return -1; |
226 { | |
227 if (!config.isMember("Database") || | |
228 config["Database"].type() != Json::stringValue) | |
229 { | |
230 OrthancPluginLogError(context_, "The configuration option \"Worklists.Database\" must contain a path"); | |
231 return -1; | |
232 } | |
233 | |
234 folder_ = config["Database"].asString(); | |
235 } | |
236 else | |
237 { | |
238 OrthancPluginLogWarning(context_, "Worklists server is disabled by the configuration file"); | |
239 } | |
240 } | 182 } |
241 } | 183 } |
242 else | 184 else |
243 { | 185 { |
244 OrthancPluginLogWarning(context_, "Worklists server is disabled, no suitable configuration section was provided"); | 186 OrthancPlugins::LogWarning(context_, "Worklists server is disabled by the configuration file"); |
245 } | |
246 | |
247 if (enabled) | |
248 { | |
249 std::string message = "The database of worklists will be read from folder: " + folder_; | |
250 OrthancPluginLogWarning(context_, message.c_str()); | |
251 | |
252 OrthancPluginRegisterWorklistCallback(context_, Callback); | |
253 } | 187 } |
254 | 188 |
255 return 0; | 189 return 0; |
256 } | 190 } |
257 | 191 |