comparison Plugins/Samples/ModalityWorklists/Plugin.cpp @ 1802:138664eb59de worklists

sample worklist plugin
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 20 Nov 2015 15:54:07 +0100
parents
children 9c2ffc4e938b
comparison
equal deleted inserted replaced
1801:2c60c357ee3e 1802:138664eb59de
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
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>
28
29 static OrthancPluginContext* context_ = NULL;
30 static std::string folder_;
31
32
33 static bool ReadFile(std::string& result,
34 const std::string& path)
35 {
36 OrthancPluginMemoryBuffer tmp;
37 if (OrthancPluginReadFile(context_, &tmp, path.c_str()))
38 {
39 return false;
40 }
41 else
42 {
43 result.assign(reinterpret_cast<const char*>(tmp.data), tmp.size);
44 OrthancPluginFreeMemoryBuffer(context_, &tmp);
45 return true;
46 }
47 }
48
49
50 /**
51 * This is the main function for matching a DICOM worklist against a query.
52 **/
53 static OrthancPluginErrorCode MatchWorklist(OrthancPluginWorklistAnswers* answers,
54 const OrthancPluginWorklistQuery* query,
55 const std::string& path)
56 {
57 std::string dicom;
58 if (!ReadFile(dicom, path))
59 {
60 // Cannot read this file, ignore this error
61 return OrthancPluginErrorCode_Success;
62 }
63
64 if (OrthancPluginIsWorklistMatch(context_, query, dicom.c_str(), dicom.size()))
65 {
66 // This DICOM file matches the worklist query, add it to the answers
67 return OrthancPluginWorklistAddWorklistAnswer
68 (context_, answers, query, dicom.c_str(), dicom.size());
69 }
70 else
71 {
72 // This DICOM file does not match
73 return OrthancPluginErrorCode_Success;
74 }
75 }
76
77
78
79 static bool ConvertToJson(Json::Value& result,
80 char* content)
81 {
82 if (content == NULL)
83 {
84 return false;
85 }
86 else
87 {
88 Json::Reader reader;
89 bool success = reader.parse(content, content + strlen(content), result);
90 OrthancPluginFreeString(context_, content);
91 return success;
92 }
93 }
94
95
96
97 static bool GetQueryDicom(Json::Value& value,
98 const OrthancPluginWorklistQuery* query)
99 {
100 OrthancPluginMemoryBuffer dicom;
101 if (OrthancPluginGetWorklistQueryDicom(context_, &dicom, query))
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
116 OrthancPluginErrorCode Callback(OrthancPluginWorklistAnswers* answers,
117 const OrthancPluginWorklistQuery* query,
118 const char* remoteAet,
119 const char* calledAet)
120 {
121 Json::Value json;
122
123 if (!GetQueryDicom(json, query))
124 {
125 return OrthancPluginErrorCode_InternalError;
126 }
127
128 std::cout << "Received worklist query from remote modality " << remoteAet
129 << ":" << std::endl << json.toStyledString();
130
131 boost::filesystem::path source(folder_);
132 boost::filesystem::directory_iterator end;
133
134 try
135 {
136 for (boost::filesystem::directory_iterator it(source); it != end; ++it)
137 {
138 if (is_regular_file(it->status()))
139 {
140 std::string extension = boost::filesystem::extension(it->path());
141 if (!strcasecmp(".wl", extension.c_str()))
142 {
143 OrthancPluginErrorCode error = MatchWorklist(answers, query, it->path().string());
144 if (error)
145 {
146 OrthancPluginLogError(context_, "Error while adding an answer to a worklist request");
147 return error;
148 }
149 }
150 }
151 }
152 }
153 catch (boost::filesystem::filesystem_error&)
154 {
155 std::string description = std::string("Inexistent folder while scanning for worklists: ") + source.string();
156 OrthancPluginLogError(context_, description.c_str());
157 return OrthancPluginErrorCode_DirectoryExpected;
158 }
159
160 // Uncomment the following line if too many answers are to be returned
161 // OrthancPluginMarkWorklistAnswersIncomplete(context_, answers);
162
163 return OrthancPluginErrorCode_Success;
164 }
165
166
167 extern "C"
168 {
169 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
170 {
171 context_ = c;
172 OrthancPluginLogWarning(context_, "Storage plugin is initializing");
173
174 /* Check the version of the Orthanc core */
175 if (OrthancPluginCheckVersion(c) == 0)
176 {
177 char info[1024];
178 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
179 context_->orthancVersion,
180 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
181 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
182 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
183 OrthancPluginLogError(context_, info);
184 return -1;
185 }
186
187 Json::Value configuration;
188 if (!ConvertToJson(configuration, OrthancPluginGetConfiguration(context_)))
189 {
190 OrthancPluginLogError(context_, "Cannot access the configuration");
191 return -1;
192 }
193
194 if (configuration.isMember("WorklistsFolder"))
195 {
196 if (configuration["WorklistsFolder"].type() != Json::stringValue)
197 {
198 OrthancPluginLogError(context_, "The configuration option \"WorklistsFolder\" must be a string");
199 return -1;
200 }
201
202 folder_ = configuration["WorklistsFolder"].asString();
203 }
204 else
205 {
206 folder_ = DEFAULT_WORKLISTS_FOLDER;
207 }
208
209 std::string message = "The database of worklists will be read from folder: " + folder_;
210 OrthancPluginLogWarning(context_, message.c_str());
211
212 OrthancPluginRegisterWorklistCallback(context_, Callback);
213
214 return 0;
215 }
216
217
218 ORTHANC_PLUGINS_API void OrthancPluginFinalize()
219 {
220 OrthancPluginLogWarning(context_, "Sample worklist plugin is finalizing");
221 }
222
223
224 ORTHANC_PLUGINS_API const char* OrthancPluginGetName()
225 {
226 return "sample-worklists";
227 }
228
229
230 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion()
231 {
232 return SAMPLE_MODALITY_WORKLISTS_VERSION;
233 }
234 }