comparison OrthancFramework/Sources/DicomFormat/DicomPath.cpp @ 4681:c5528c7847a6

new class DicomPath
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 07 Jun 2021 17:05:48 +0200
parents
children d38a7040474a
comparison
equal deleted inserted replaced
4680:898e8ac8c453 4681:c5528c7847a6
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-2021 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program. If not, see
19 * <http://www.gnu.org/licenses/>.
20 **/
21
22
23 #include "../PrecompiledHeaders.h"
24 #include "DicomPath.h"
25
26
27 #if !defined(ORTHANC_ENABLE_DCMTK)
28 # error Macro ORTHANC_ENABLE_DCMTK must be defined
29 #endif
30
31 #if ORTHANC_ENABLE_DCMTK == 1
32 # include "../DicomParsing/FromDcmtkBridge.h"
33 #endif
34
35 #include "../OrthancException.h"
36 #include "../Toolbox.h"
37
38 #include <boost/lexical_cast.hpp>
39
40
41 namespace Orthanc
42 {
43 DicomPath::PrefixItem::PrefixItem(DicomTag tag,
44 bool isUniversal,
45 size_t index) :
46 tag_(tag),
47 isUniversal_(isUniversal),
48 index_(index)
49 {
50 }
51
52
53 size_t DicomPath::PrefixItem::GetIndex() const
54 {
55 if (isUniversal_)
56 {
57 throw OrthancException(ErrorCode_BadSequenceOfCalls);
58 }
59 else
60 {
61 return index_;
62 }
63 }
64
65
66 DicomTag DicomPath::ParseTag(const std::string& token)
67 {
68 DicomTag tag(0,0);
69
70 if (token[0] == '(' &&
71 token[token.size() - 1] == ')')
72 {
73 std::string hex = token.substr(1, token.size() - 2);
74 if (!DicomTag::ParseHexadecimal(tag, hex.c_str()))
75 {
76 throw OrthancException(ErrorCode_UnknownDicomTag, "Cannot parse tag: " + token);
77 }
78 }
79 else
80 {
81 #if ORTHANC_ENABLE_DCMTK == 1
82 tag = FromDcmtkBridge::ParseTag(token);
83 #else
84 if (!DicomTag::ParseHexadecimal(tag, token.c_str()))
85 {
86 throw OrthancException(ErrorCode_UnknownDicomTag, "Cannot parse tag without DCMTK: " + token);
87 }
88 #endif
89 }
90
91 return tag;
92 }
93
94
95 const DicomPath::PrefixItem& DicomPath::GetLevel(size_t i) const
96 {
97 if (i >= prefix_.size())
98 {
99 throw OrthancException(ErrorCode_ParameterOutOfRange);
100 }
101 else
102 {
103 return prefix_[i];
104 }
105 }
106
107
108 DicomPath::DicomPath(const Orthanc::DicomTag& sequence,
109 size_t index,
110 const Orthanc::DicomTag& tag) :
111 finalTag_(tag)
112 {
113 AddIndexedTagToPrefix(sequence, index);
114 }
115
116
117 DicomPath::DicomPath(const Orthanc::DicomTag& sequence1,
118 size_t index1,
119 const Orthanc::DicomTag& sequence2,
120 size_t index2,
121 const Orthanc::DicomTag& tag) :
122 finalTag_(tag)
123 {
124 AddIndexedTagToPrefix(sequence1, index1);
125 AddIndexedTagToPrefix(sequence2, index2);
126 }
127
128
129 DicomPath::DicomPath(const Orthanc::DicomTag& sequence1,
130 size_t index1,
131 const Orthanc::DicomTag& sequence2,
132 size_t index2,
133 const Orthanc::DicomTag& sequence3,
134 size_t index3,
135 const Orthanc::DicomTag& tag) :
136 finalTag_(tag)
137 {
138 AddIndexedTagToPrefix(sequence1, index1);
139 AddIndexedTagToPrefix(sequence2, index2);
140 AddIndexedTagToPrefix(sequence3, index3);
141 }
142
143
144 void DicomPath::AddIndexedTagToPrefix(const Orthanc::DicomTag& tag,
145 size_t index)
146 {
147 prefix_.push_back(PrefixItem::CreateIndexed(tag, index));
148 }
149
150
151 void DicomPath::AddUniversalTagToPrefix(const Orthanc::DicomTag& tag)
152 {
153 prefix_.push_back(PrefixItem::CreateUniversal(tag));
154 }
155
156
157 std::string DicomPath::Format() const
158 {
159 std::string s;
160
161 for (size_t i = 0; i < prefix_.size(); i++)
162 {
163 s += "(" + prefix_[i].GetTag().Format() + ")";
164
165 if (prefix_[i].IsUniversal())
166 {
167 s += "[*].";
168 }
169 else
170 {
171 s += "[" + boost::lexical_cast<std::string>(prefix_[i].GetIndex()) + "].";
172 }
173 }
174
175 return s + "(" + finalTag_.Format() + ")";
176 }
177
178
179 DicomPath DicomPath::Parse(const std::string& s,
180 bool allowUniversal)
181 {
182 std::vector<std::string> tokens;
183 Toolbox::TokenizeString(tokens, s, '.');
184
185 if (tokens.empty())
186 {
187 throw OrthancException(ErrorCode_ParameterOutOfRange, "Empty path to DICOM tags");
188 }
189
190 const DicomTag finalTag = ParseTag(Toolbox::StripSpaces(tokens[tokens.size() - 1]));
191
192 DicomPath path(finalTag);
193
194 for (size_t i = 0; i < tokens.size() - 1; i++)
195 {
196 size_t pos = tokens[i].find('[');
197 if (pos == std::string::npos)
198 {
199 throw OrthancException(ErrorCode_ParameterOutOfRange, "Parent path doesn't contain an index");
200 }
201 else
202 {
203 const std::string left = Orthanc::Toolbox::StripSpaces(tokens[i].substr(0, pos));
204 const std::string right = Orthanc::Toolbox::StripSpaces(tokens[i].substr(pos + 1));
205
206 if (left.empty())
207 {
208 throw OrthancException(ErrorCode_ParameterOutOfRange, "Parent path doesn't contain a tag");
209 }
210 else if (right.empty() ||
211 right[right.size() - 1] != ']')
212 {
213 throw OrthancException(ErrorCode_ParameterOutOfRange, "Parent path doesn't contain the end of the index");
214 }
215 else
216 {
217 DicomTag tag = ParseTag(left);
218
219 try
220 {
221 std::string s = Toolbox::StripSpaces(right.substr(0, right.size() - 1));
222 if (s == "*")
223 {
224 if (allowUniversal)
225 {
226 path.AddUniversalTagToPrefix(tag);
227 }
228 else
229 {
230 throw OrthancException(ErrorCode_ParameterOutOfRange, "Cannot create an universal parent path");
231 }
232 }
233 else
234 {
235 int index = boost::lexical_cast<int>(s);
236 if (index < 0)
237 {
238 throw OrthancException(ErrorCode_ParameterOutOfRange, "Negative index in parent path: " + s);
239 }
240 else
241 {
242 path.AddIndexedTagToPrefix(tag, static_cast<size_t>(index));
243 }
244 }
245 }
246 catch (boost::bad_lexical_cast&)
247 {
248 throw OrthancException(ErrorCode_ParameterOutOfRange, "Not a valid index in parent path: [" + right);
249 }
250 }
251 }
252 }
253
254 return path;
255 }
256 }