Mercurial > hg > orthanc
comparison OrthancServer/Plugins/Samples/MultitenantDicom/PluginToolbox.cpp @ 5273:7cb1b851f5c8
Added a sample plugin bringing multitenant DICOM support through labels
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 14 Apr 2023 11:49:24 +0200 |
parents | |
children | a8385880902f |
comparison
equal
deleted
inserted
replaced
5272:a45e8b6115f6 | 5273:7cb1b851f5c8 |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium | |
6 * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium | |
7 * | |
8 * This program is free software: you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public License | |
10 * as published by the Free Software Foundation, either version 3 of | |
11 * the License, or (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, but | |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with this program. If not, see | |
20 * <http://www.gnu.org/licenses/>. | |
21 **/ | |
22 | |
23 | |
24 #include "PluginToolbox.h" | |
25 | |
26 #include "../../../../OrthancFramework/Sources/OrthancException.h" | |
27 #include "../../../../OrthancFramework/Sources/SerializationToolbox.h" | |
28 #include "../../../../OrthancFramework/Sources/Toolbox.h" | |
29 | |
30 #include "../Common/OrthancPluginCppWrapper.h" | |
31 | |
32 | |
33 namespace PluginToolbox | |
34 { | |
35 bool IsValidLabel(const std::string& label) | |
36 { | |
37 if (label.empty()) | |
38 { | |
39 return false; | |
40 } | |
41 | |
42 if (label.size() > 64) | |
43 { | |
44 // This limitation is for MySQL, which cannot use a TEXT | |
45 // column of undefined length as a primary key | |
46 return false; | |
47 } | |
48 | |
49 for (size_t i = 0; i < label.size(); i++) | |
50 { | |
51 if (!(label[i] == '_' || | |
52 label[i] == '-' || | |
53 (label[i] >= 'a' && label[i] <= 'z') || | |
54 (label[i] >= 'A' && label[i] <= 'Z') || | |
55 (label[i] >= '0' && label[i] <= '9'))) | |
56 { | |
57 return false; | |
58 } | |
59 } | |
60 | |
61 return true; | |
62 } | |
63 | |
64 | |
65 Orthanc::ResourceType ParseQueryRetrieveLevel(const std::string& level) | |
66 { | |
67 if (level == "PATIENT") | |
68 { | |
69 return Orthanc::ResourceType_Patient; | |
70 } | |
71 else if (level == "STUDY") | |
72 { | |
73 return Orthanc::ResourceType_Study; | |
74 } | |
75 else if (level == "SERIES") | |
76 { | |
77 return Orthanc::ResourceType_Series; | |
78 } | |
79 else if (level == "INSTANCE") | |
80 { | |
81 return Orthanc::ResourceType_Instance; | |
82 } | |
83 else | |
84 { | |
85 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Bad value for QueryRetrieveLevel in DICOM C-FIND: " + level); | |
86 } | |
87 } | |
88 | |
89 | |
90 bool IsSameAETitle(bool isStrict, | |
91 const std::string& aet1, | |
92 const std::string& aet2) | |
93 { | |
94 if (isStrict) | |
95 { | |
96 // Case-sensitive matching | |
97 return aet1 == aet2; | |
98 } | |
99 else | |
100 { | |
101 // Case-insensitive matching (default) | |
102 std::string tmp1, tmp2; | |
103 Orthanc::Toolbox::ToLowerCase(tmp1, aet1); | |
104 Orthanc::Toolbox::ToLowerCase(tmp2, aet2); | |
105 return tmp1 == tmp2; | |
106 } | |
107 } | |
108 | |
109 | |
110 bool LookupAETitle(std::string& name, | |
111 Orthanc::RemoteModalityParameters& parameters, | |
112 bool isStrict, | |
113 const std::string& aet) | |
114 { | |
115 Json::Value modalities; | |
116 if (!OrthancPlugins::RestApiGet(modalities, "/modalities?expand", false)) | |
117 { | |
118 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to obtain the list of the remote modalities"); | |
119 } | |
120 | |
121 std::vector<std::string> names = modalities.getMemberNames(); | |
122 for (size_t i = 0; i < names.size(); i++) | |
123 { | |
124 parameters = Orthanc::RemoteModalityParameters(modalities[names[i]]); | |
125 | |
126 if (IsSameAETitle(isStrict, parameters.GetApplicationEntityTitle(), aet)) | |
127 { | |
128 name = names[i]; | |
129 return true; | |
130 } | |
131 } | |
132 | |
133 return false; | |
134 } | |
135 | |
136 | |
137 void ParseLabels(std::set<std::string>& targetLabels, | |
138 LabelsConstraint& targetConstraint, | |
139 const Json::Value& serverConfig) | |
140 { | |
141 Orthanc::SerializationToolbox::ReadSetOfStrings(targetLabels, serverConfig, KEY_LABELS); | |
142 | |
143 for (std::set<std::string>::const_iterator it = targetLabels.begin(); it != targetLabels.end(); ++it) | |
144 { | |
145 if (!PluginToolbox::IsValidLabel(*it)) | |
146 { | |
147 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "Invalid label: " + *it); | |
148 } | |
149 } | |
150 | |
151 std::string s = Orthanc::SerializationToolbox::ReadString(serverConfig, KEY_LABELS_CONSTRAINT, KEY_ALL); | |
152 targetConstraint = PluginToolbox::StringToLabelsConstraint(s); | |
153 } | |
154 | |
155 | |
156 void AddLabelsToFindRequest(Json::Value& request, | |
157 const std::set<std::string>& labels, | |
158 LabelsConstraint constraint) | |
159 { | |
160 Json::Value items = Json::arrayValue; | |
161 for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it) | |
162 { | |
163 items.append(*it); | |
164 } | |
165 | |
166 request[KEY_LABELS] = items; | |
167 | |
168 switch (constraint) | |
169 { | |
170 case LabelsConstraint_All: | |
171 request[KEY_LABELS_CONSTRAINT] = KEY_ALL; | |
172 break; | |
173 | |
174 case LabelsConstraint_Any: | |
175 request[KEY_LABELS_CONSTRAINT] = KEY_ANY; | |
176 break; | |
177 | |
178 case LabelsConstraint_None: | |
179 request[KEY_LABELS_CONSTRAINT] = KEY_NONE; | |
180 break; | |
181 | |
182 default: | |
183 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
184 } | |
185 } | |
186 | |
187 | |
188 LabelsConstraint StringToLabelsConstraint(const std::string& s) | |
189 { | |
190 if (s == KEY_ALL) | |
191 { | |
192 return LabelsConstraint_All; | |
193 } | |
194 else if (s == KEY_ANY) | |
195 { | |
196 return LabelsConstraint_Any; | |
197 } | |
198 else if (s == KEY_NONE) | |
199 { | |
200 return LabelsConstraint_None; | |
201 } | |
202 else | |
203 { | |
204 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "Bad value for constraint of labels: " + s); | |
205 } | |
206 } | |
207 } |