comparison OrthancServer/Search/HierarchicalMatcher.cpp @ 3071:2df061cf2fec db-changes

getting rid of IFindConstraint hierarchy
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 02 Jan 2019 11:26:27 +0100
parents 4e43e67f8ecf
children 1b05fd072c57
comparison
equal deleted inserted replaced
3070:1bc4a1bb66e9 3071:2df061cf2fec
57 } 57 }
58 58
59 59
60 HierarchicalMatcher::~HierarchicalMatcher() 60 HierarchicalMatcher::~HierarchicalMatcher()
61 { 61 {
62 for (Constraints::iterator it = constraints_.begin();
63 it != constraints_.end(); ++it)
64 {
65 if (it->second != NULL)
66 {
67 delete it->second;
68 }
69 }
70
71 for (Sequences::iterator it = sequences_.begin(); 62 for (Sequences::iterator it = sequences_.begin();
72 it != sequences_.end(); ++it) 63 it != sequences_.end(); ++it)
73 { 64 {
74 if (it->second != NULL) 65 if (it->second != NULL)
75 { 66 {
96 tag.GetElement() == 0x0000) // Ignore all "Group Length" tags 87 tag.GetElement() == 0x0000) // Ignore all "Group Length" tags
97 { 88 {
98 continue; 89 continue;
99 } 90 }
100 91
101 ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(tag); 92 if (flatTags_.find(tag) != flatTags_.end() ||
102
103 if (constraints_.find(tag) != constraints_.end() ||
104 sequences_.find(tag) != sequences_.end()) 93 sequences_.find(tag) != sequences_.end())
105 { 94 {
95 // A constraint already exists on this tag
106 throw OrthancException(ErrorCode_BadRequest); 96 throw OrthancException(ErrorCode_BadRequest);
107 } 97 }
108 98
109 if (vr == ValueRepresentation_Sequence) 99 if (FromDcmtkBridge::LookupValueRepresentation(tag) == ValueRepresentation_Sequence)
110 { 100 {
111 DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element); 101 DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element);
112 102
113 if (sequence.card() == 0 || 103 if (sequence.card() == 0 ||
114 (sequence.card() == 1 && sequence.getItem(0)->card() == 0)) 104 (sequence.card() == 1 && sequence.getItem(0)->card() == 0))
130 std::set<DicomTag> ignoreTagLength; 120 std::set<DicomTag> ignoreTagLength;
131 std::auto_ptr<DicomValue> value(FromDcmtkBridge::ConvertLeafElement 121 std::auto_ptr<DicomValue> value(FromDcmtkBridge::ConvertLeafElement
132 (*element, DicomToJsonFlags_None, 122 (*element, DicomToJsonFlags_None,
133 ORTHANC_MAXIMUM_TAG_LENGTH, encoding, ignoreTagLength)); 123 ORTHANC_MAXIMUM_TAG_LENGTH, encoding, ignoreTagLength));
134 124
125 flatTags_.insert(tag);
126
135 if (value->IsBinary()) 127 if (value->IsBinary())
136 { 128 {
137 if (!value->GetContent().empty()) 129 if (!value->GetContent().empty())
138 { 130 {
139 LOG(WARNING) << "This C-Find modality worklist query contains a non-empty tag (" 131 LOG(WARNING) << "This C-Find modality worklist query contains a non-empty tag ("
140 << tag.Format() << ") with UN (unknown) value representation. " 132 << tag.Format() << ") with UN (unknown) value representation. "
141 << "It will be ignored."; 133 << "It will be ignored.";
142 } 134 }
143
144 constraints_[tag] = NULL;
145 } 135 }
146 else if (value->IsNull() || 136 else if (value->IsNull() ||
147 value->GetContent().empty()) 137 value->GetContent().empty())
148 { 138 {
149 // This is an universal matcher 139 // This is an universal matcher
150 constraints_[tag] = NULL;
151 } 140 }
152 else 141 else
153 { 142 {
154 // DICOM specifies that searches must be case sensitive, except 143 flatConstraints_.AddDicomConstraint
155 // for tags with a PN value representation 144 (tag, value->GetContent(), caseSensitivePN, true /* mandatory */);
156 bool sensitive = true;
157 if (vr == ValueRepresentation_PersonName)
158 {
159 sensitive = caseSensitivePN;
160 }
161
162 constraints_[tag] = IFindConstraint::ParseDicomConstraint(tag, value->GetContent(), sensitive);
163 } 145 }
164 } 146 }
165 } 147 }
166 } 148 }
167 149
168 150
169 std::string HierarchicalMatcher::Format(const std::string& prefix) const 151 std::string HierarchicalMatcher::Format(const std::string& prefix) const
170 { 152 {
171 std::string s; 153 std::string s;
154
155 std::set<DicomTag> tags;
156 for (size_t i = 0; i < flatConstraints_.GetConstraintsCount(); i++)
157 {
158 const DicomTagConstraint& c = flatConstraints_.GetConstraint(i);
159
160 s += c.Format() + "\n";
161 tags.insert(c.GetTag());
162 }
172 163
173 for (Constraints::const_iterator it = constraints_.begin(); 164 // Loop over the universal constraints
174 it != constraints_.end(); ++it) 165 for (std::set<DicomTag>::const_iterator it = flatTags_.begin();
175 { 166 it != flatTags_.end(); ++it)
176 s += prefix + it->first.Format() + " "; 167 {
177 168 if (tags.find(*it) == tags.end())
178 if (it->second == NULL) 169 {
179 { 170 s += prefix + it->Format() + " == *\n";
180 s += "*\n";
181 }
182 else
183 {
184 s += it->second->Format() + "\n";
185 } 171 }
186 } 172 }
187 173
188 for (Sequences::const_iterator it = sequences_.begin(); 174 for (Sequences::const_iterator it = sequences_.begin();
189 it != sequences_.end(); ++it) 175 it != sequences_.end(); ++it)
212 198
213 199
214 bool HierarchicalMatcher::MatchInternal(DcmItem& item, 200 bool HierarchicalMatcher::MatchInternal(DcmItem& item,
215 Encoding encoding) const 201 Encoding encoding) const
216 { 202 {
217 for (Constraints::const_iterator it = constraints_.begin(); 203 if (!flatConstraints_.IsMatch(item, encoding))
218 it != constraints_.end(); ++it) 204 {
219 { 205 return false;
220 if (it->second != NULL) 206 }
221 { 207
222 DcmTagKey tag = ToDcmtkBridge::Convert(it->first);
223
224 DcmElement* element = NULL;
225 if (!item.findAndGetElement(tag, element).good() ||
226 element == NULL)
227 {
228 return false;
229 }
230
231 std::set<DicomTag> ignoreTagLength;
232 std::auto_ptr<DicomValue> value(FromDcmtkBridge::ConvertLeafElement
233 (*element, DicomToJsonFlags_None,
234 ORTHANC_MAXIMUM_TAG_LENGTH, encoding, ignoreTagLength));
235
236 if (value->IsNull() ||
237 value->IsBinary() ||
238 !it->second->Match(value->GetContent()))
239 {
240 return false;
241 }
242 }
243 }
244
245 for (Sequences::const_iterator it = sequences_.begin(); 208 for (Sequences::const_iterator it = sequences_.begin();
246 it != sequences_.end(); ++it) 209 it != sequences_.end(); ++it)
247 { 210 {
248 if (it->second != NULL) 211 if (it->second != NULL)
249 { 212 {
281 DcmDataset* HierarchicalMatcher::ExtractInternal(DcmItem& source, 244 DcmDataset* HierarchicalMatcher::ExtractInternal(DcmItem& source,
282 Encoding encoding) const 245 Encoding encoding) const
283 { 246 {
284 std::auto_ptr<DcmDataset> target(new DcmDataset); 247 std::auto_ptr<DcmDataset> target(new DcmDataset);
285 248
286 for (Constraints::const_iterator it = constraints_.begin(); 249 for (std::set<DicomTag>::const_iterator it = flatTags_.begin();
287 it != constraints_.end(); ++it) 250 it != flatTags_.end(); ++it)
288 { 251 {
289 DcmTagKey tag = ToDcmtkBridge::Convert(it->first); 252 DcmTagKey tag = ToDcmtkBridge::Convert(*it);
290 253
291 DcmElement* element = NULL; 254 DcmElement* element = NULL;
292 if (source.findAndGetElement(tag, element).good() && 255 if (source.findAndGetElement(tag, element).good() &&
293 element != NULL) 256 element != NULL)
294 { 257 {
295 std::auto_ptr<DcmElement> cloned(FromDcmtkBridge::CreateElementForTag(it->first)); 258 std::auto_ptr<DcmElement> cloned(FromDcmtkBridge::CreateElementForTag(*it));
296 cloned->copyFrom(*element); 259 cloned->copyFrom(*element);
297 target->insert(cloned.release()); 260 target->insert(cloned.release());
298 } 261 }
299 } 262 }
300 263