1 /*
2  *
3  *  Copyright (C) 2015-2020, Open Connections GmbH
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation are maintained by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module: dcmiod
15  *
16  *  Author: Michael Onken
17  *
18  *  Purpose: Collection of classes representing DICOM IOD macros
19  *
20  */
21 
22 #include "dcmtk/dcmiod/iodmacro.h"
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmiod/iodutil.h"  // for static IOD helpers
25 #include "dcmtk/ofstd/ofstream.h"
26 
27 // --------------------------- Code Sequence Macro ---------------------------
28 
29 // -- Code Sequence Macro
30 
CodeSequenceMacro(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent)31 CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules, IODComponent* parent)
32     : IODComponent(item, rules, parent)
33 {
34     // reset element rules
35     resetRules();
36 }
37 
CodeSequenceMacro(IODComponent * parent)38 CodeSequenceMacro::CodeSequenceMacro(IODComponent* parent)
39     : IODComponent(parent)
40 {
41     // reset element rules
42     resetRules();
43 }
44 
CodeSequenceMacro(const CodeSequenceMacro & rhs)45 CodeSequenceMacro::CodeSequenceMacro(const CodeSequenceMacro& rhs)
46     : IODComponent(rhs)
47 {
48 }
49 
~CodeSequenceMacro()50 CodeSequenceMacro::~CodeSequenceMacro()
51 {
52     // nothing to do
53 }
54 
CodeSequenceMacro(const OFString & codeValue,const OFString & codingSchemeDesignator,const OFString & codeMeaning,const OFString & codingSchemeVersion,IODComponent * parent)55 CodeSequenceMacro::CodeSequenceMacro(const OFString& codeValue,
56                                      const OFString& codingSchemeDesignator,
57                                      const OFString& codeMeaning,
58                                      const OFString& codingSchemeVersion,
59                                      IODComponent* parent)
60     : IODComponent(parent)
61 {
62     // reset element rules
63     resetRules();
64     set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion);
65 }
66 
check(const bool quiet)67 OFCondition CodeSequenceMacro::check(const bool quiet)
68 {
69     OFString val;
70     getCodeValue(val);
71     if (!val.empty())
72         getCodingSchemeDesignator(val);
73     if (!val.empty())
74         getCodeMeaning(val);
75     if (!val.empty())
76         return EC_Normal;
77 
78     return EC_IllegalParameter;
79 }
80 
CodeSequenceMacro(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent,const OFString & codeValue,const OFString & codingSchemeDesignator,const OFString & codeMeaning,const OFString & codingSchemeVersion)81 CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr<DcmItem> item,
82                                      OFshared_ptr<IODRules> rules,
83                                      IODComponent* parent,
84                                      const OFString& codeValue,
85                                      const OFString& codingSchemeDesignator,
86                                      const OFString& codeMeaning,
87                                      const OFString& codingSchemeVersion)
88     : IODComponent(item, rules, parent)
89 {
90     // reset element rules
91     resetRules();
92     set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion);
93 }
94 
getName() const95 OFString CodeSequenceMacro::getName() const
96 {
97     return "CodeSequenceMacro";
98 }
99 
resetRules()100 void CodeSequenceMacro::resetRules()
101 {
102     m_Rules->addRule(new IODRule(DCM_CodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED),
103                      OFTrue /*overwrite old rule*/);
104     m_Rules->addRule(new IODRule(DCM_URNCodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED),
105                      OFTrue /*overwrite old rule*/);
106     m_Rules->addRule(new IODRule(DCM_LongCodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED),
107                      OFTrue /*overwrite old rule*/);
108     m_Rules->addRule(new IODRule(DCM_CodingSchemeDesignator, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED),
109                      OFTrue /*overwrite old rule*/);
110     m_Rules->addRule(new IODRule(DCM_CodingSchemeVersion, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED),
111                      OFTrue /*overwrite old rule*/);
112     m_Rules->addRule(new IODRule(DCM_CodeMeaning, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED),
113                      OFTrue /*overwrite old rule*/);
114 }
115 
116 // -- get dicom attributes --
117 
getCodeValue(OFString & value,const signed long pos,const OFBool autoTag)118 OFCondition CodeSequenceMacro::getCodeValue(OFString& value, const signed long pos, const OFBool autoTag)
119 {
120     OFString c;
121     OFCondition cond = DcmIODUtil::getStringValueFromItem(DCM_CodeValue, *m_Item, value, pos);
122     if (cond.good() || ((cond == EC_TagNotFound) && !autoTag))
123         return cond;
124 
125     cond = DcmIODUtil::getStringValueFromItem(DCM_URNCodeValue, *m_Item, value, pos);
126     if (cond != EC_TagNotFound)
127         return cond;
128 
129     cond = DcmIODUtil::getStringValueFromItem(DCM_LongCodeValue, *m_Item, value, pos);
130     return cond;
131 }
132 
getURNCodeValue(OFString & value,const signed long pos)133 OFCondition CodeSequenceMacro::getURNCodeValue(OFString& value, const signed long pos)
134 {
135     return DcmIODUtil::getStringValueFromItem(DCM_URNCodeValue, *m_Item, value, pos);
136 }
137 
getLongCodeValue(OFString & value,const signed long pos)138 OFCondition CodeSequenceMacro::getLongCodeValue(OFString& value, const signed long pos)
139 {
140     return DcmIODUtil::getStringValueFromItem(DCM_LongCodeValue, *m_Item, value, pos);
141 }
142 
getCodingSchemeDesignator(OFString & value,const signed long pos)143 OFCondition CodeSequenceMacro::getCodingSchemeDesignator(OFString& value, const signed long pos)
144 {
145     return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeDesignator, *m_Item, value, pos);
146 }
147 
getCodingSchemeVersion(OFString & value,const signed long pos)148 OFCondition CodeSequenceMacro::getCodingSchemeVersion(OFString& value, const signed long pos)
149 {
150     return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeVersion, *m_Item, value, pos);
151 }
152 
getCodeMeaning(OFString & value,const signed long pos)153 OFCondition CodeSequenceMacro::getCodeMeaning(OFString& value, const signed long pos)
154 {
155     return DcmIODUtil::getStringValueFromItem(DCM_CodeMeaning, *m_Item, value, pos);
156 }
157 
empty()158 OFBool CodeSequenceMacro::empty()
159 {
160     OFString val;
161     getCodeValue(val);
162     if (val.empty())
163     {
164         getCodingSchemeDesignator(val);
165         if (val.empty())
166         {
167             getCodingSchemeVersion(val);
168             if (val.empty())
169             {
170                 getCodingSchemeDesignator(val);
171                 if (val.empty())
172                 {
173                     return OFTrue;
174                 }
175             }
176         }
177     }
178     return OFFalse;
179 }
180 
181 // -- set dicom attributes --
182 
setCodeValue(const OFString & value,const OFBool checkValue,const OFBool autoTag)183 OFCondition CodeSequenceMacro::setCodeValue(const OFString& value, const OFBool checkValue, const OFBool autoTag)
184 {
185     OFCondition result;
186 
187     // Identify the code value tag to be used
188     if (autoTag)
189     {
190         if ((value.find("://") != OFString_npos) || (value.compare(0, 4, "urn:") == 0))
191         {
192             return setURNCodeValue(value, checkValue);
193         }
194         else if (value.length() > 16) // Long Code Value
195         {
196             return setLongCodeValue(value, checkValue);
197         }
198     }
199     // Classic Code Value
200     result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal;
201     if (result.bad())
202         return result;
203     // TODO: Should check length in characters (not bytes), since SH permits usage of
204     // non-ASCII characters (i.e. as defined in 0008,0015).
205     if (value.length() > 16)
206         return EC_MaximumLengthViolated;
207     result = m_Item->putAndInsertOFStringArray(DCM_CodeValue, value);
208     if (result.good())
209     {
210         deleteUnusedCodeValues(DCM_CodeValue);
211     }
212     return result;
213 }
214 
setURNCodeValue(const OFString & value,const bool checkValue)215 OFCondition CodeSequenceMacro::setURNCodeValue(const OFString& value, const bool checkValue)
216 {
217     OFCondition result = (checkValue) ? DcmUniversalResourceIdentifierOrLocator::checkStringValue(value) : EC_Normal;
218     if (result.good())
219         result = m_Item->putAndInsertOFStringArray(DCM_URNCodeValue, value);
220     if (result.good())
221     {
222         deleteUnusedCodeValues(DCM_URNCodeValue);
223     }
224     return result;
225 }
226 
setLongCodeValue(const OFString & value,const bool checkValue)227 OFCondition CodeSequenceMacro::setLongCodeValue(const OFString& value, const bool checkValue)
228 {
229     OFCondition result = (checkValue) ? DcmUnlimitedCharacters::checkStringValue(value, "1") : EC_Normal;
230     if (result.good())
231         result = m_Item->putAndInsertOFStringArray(DCM_LongCodeValue, value);
232     if (result.good())
233     {
234         deleteUnusedCodeValues(DCM_LongCodeValue);
235     }
236     return result;
237 }
238 
setCodingSchemeDesignator(const OFString & value,const OFBool checkValue)239 OFCondition CodeSequenceMacro::setCodingSchemeDesignator(const OFString& value, const OFBool checkValue)
240 {
241     OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal;
242     if (result.good())
243         result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeDesignator, value);
244     return result;
245 }
246 
setCodingSchemeVersion(const OFString & value,const OFBool checkValue)247 OFCondition CodeSequenceMacro::setCodingSchemeVersion(const OFString& value, const OFBool checkValue)
248 {
249     OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal;
250     if (result.good())
251         result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeVersion, value);
252     return result;
253 }
254 
setCodeMeaning(const OFString & value,const OFBool checkValue)255 OFCondition CodeSequenceMacro::setCodeMeaning(const OFString& value, const OFBool checkValue)
256 {
257     OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
258     if (result.good())
259         result = m_Item->putAndInsertOFStringArray(DCM_CodeMeaning, value);
260     return result;
261 }
262 
set(const OFString & value,const OFString & scheme,const OFString & meaning,const OFString & schemeVersion,const OFBool checkValue,const OFBool autoTag)263 OFCondition CodeSequenceMacro::set(const OFString& value,
264                                    const OFString& scheme,
265                                    const OFString& meaning,
266                                    const OFString& schemeVersion,
267                                    const OFBool checkValue,
268                                    const OFBool autoTag)
269 {
270     OFCondition result;
271     result = setCodeValue(value, checkValue, autoTag);
272     if (result.good())
273         result = setCodingSchemeDesignator(scheme, checkValue);
274     if (result.good())
275         result = setCodeMeaning(meaning, checkValue);
276     if (result.good() && !schemeVersion.empty())
277         result = setCodingSchemeVersion(schemeVersion, checkValue);
278     return result;
279 }
280 
deleteUnusedCodeValues(const DcmTagKey & keepTag)281 void CodeSequenceMacro::deleteUnusedCodeValues(const DcmTagKey& keepTag)
282 {
283     if (keepTag != DCM_CodeValue)
284         m_Item->findAndDeleteElement(DCM_CodeValue);
285     if (keepTag != DCM_URNCodeValue)
286         m_Item->findAndDeleteElement(DCM_URNCodeValue);
287     if (keepTag != DCM_LongCodeValue)
288         m_Item->findAndDeleteElement(DCM_LongCodeValue);
289 }
290 
291 // ---------------------- CodeWithModifiers----------------------
292 
CodeWithModifiers(const OFString & modifierType,const OFString & modifierVM,const DcmTagKey & modifierSeq)293 CodeWithModifiers::CodeWithModifiers(const OFString& modifierType,
294                                      const OFString& modifierVM,
295                                      const DcmTagKey& modifierSeq)
296     : CodeSequenceMacro()
297     , m_Modifiers()
298     , m_ModifierType(modifierType)
299     , m_ModifierVM(modifierVM)
300     , m_CodeModifierSeq(modifierSeq)
301 {
302     resetRules();
303 }
304 
CodeWithModifiers(const CodeWithModifiers & rhs)305 CodeWithModifiers::CodeWithModifiers(const CodeWithModifiers& rhs)
306     : CodeSequenceMacro(rhs)
307     , m_Modifiers()
308     , m_ModifierType()
309     , m_ModifierVM()
310     , m_CodeModifierSeq()
311 {
312     if (&rhs == this)
313         return;
314 
315     *this = rhs;
316 }
317 
operator =(const CodeWithModifiers & rhs)318 CodeWithModifiers& CodeWithModifiers::operator=(const CodeWithModifiers& rhs)
319 {
320     if (&rhs == this)
321         return *this;
322 
323     CodeSequenceMacro::operator=(rhs);
324 
325     const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs);
326     if (r)
327     {
328         OFVector<CodeSequenceMacro*>::const_iterator it = r->m_Modifiers.begin();
329         while ((it != r->m_Modifiers.end()))
330         {
331             m_Modifiers.push_back(new CodeSequenceMacro(*it));
332             it++;
333         }
334     }
335 
336     return *this;
337 }
338 
check(const OFBool quiet)339 OFCondition CodeWithModifiers::check(const OFBool quiet)
340 {
341     OFCondition result = CodeSequenceMacro::check(quiet);
342     if (result.good())
343     {
344         OFVector<CodeSequenceMacro*>::iterator it = m_Modifiers.begin();
345         while (result.good() && (it != m_Modifiers.end()))
346         {
347             result = (*it)->check(quiet);
348             it++;
349         }
350     }
351     if (result.bad())
352     {
353         if (!quiet)
354         {
355             DCMIOD_ERROR("Invalid code in Code Sequence Macro or its modifiers");
356         }
357     }
358     return result;
359 }
360 
clearData()361 void CodeWithModifiers::clearData()
362 {
363     CodeSequenceMacro::clearData();
364     DcmIODUtil::freeContainer(m_Modifiers);
365 }
366 
compare(const IODComponent & rhs) const367 int CodeWithModifiers::compare(const IODComponent& rhs) const
368 {
369     const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs);
370     if (!r)
371         return -1;
372 
373     if (m_Modifiers.size() < r->m_Modifiers.size())
374         return -1;
375     else if (m_Modifiers.size() > r->m_Modifiers.size())
376         return 1;
377 
378     int result = IODComponent::compare(*r);
379     if (result == 0)
380     {
381         for (size_t n = 0; (n < m_Modifiers.size()) && (result == 0); n++)
382         {
383             result = m_Modifiers[n]->compare(*r->m_Modifiers[n]);
384         }
385     }
386     return result;
387 }
388 
getName() const389 OFString CodeWithModifiers::getName() const
390 {
391     return "CodeWithModifiers";
392 }
393 
addModifier(const CodeSequenceMacro & modifier)394 OFCondition CodeWithModifiers::addModifier(const CodeSequenceMacro& modifier)
395 {
396     OFCondition result = OFconst_cast(CodeSequenceMacro*, &modifier)->check();
397     if (result.good())
398     {
399         m_Modifiers.push_back(new CodeSequenceMacro(modifier));
400     }
401     return result;
402 }
403 
getModifier(const size_t index)404 CodeSequenceMacro* CodeWithModifiers::getModifier(const size_t index)
405 {
406     if (index + 1 > m_Modifiers.size())
407         return NULL;
408     else
409         return m_Modifiers[index];
410 }
411 
read(DcmItem & source,const OFBool clearOldData)412 OFCondition CodeWithModifiers::read(DcmItem& source, const OFBool clearOldData)
413 {
414     OFCondition result = CodeSequenceMacro::read(source, clearOldData);
415     if (result.good() && clearOldData)
416     {
417         DcmIODUtil::freeContainer(m_Modifiers);
418     }
419     if (result.good())
420     {
421         result = DcmIODUtil::readSubSequence(
422             source, m_CodeModifierSeq, m_Modifiers, getRules()->getByTag(m_CodeModifierSeq));
423     }
424     return result;
425 }
426 
resetRules()427 void CodeWithModifiers::resetRules()
428 {
429     CodeSequenceMacro::resetRules();
430     m_Rules->addRule(
431         new IODRule(m_CodeModifierSeq, m_ModifierVM, m_ModifierType, getName(), DcmIODTypes::IE_UNDEFINED));
432 }
433 
write(DcmItem & destination)434 OFCondition CodeWithModifiers::write(DcmItem& destination)
435 {
436     OFCondition result;
437     DcmIODUtil::writeSubSequence(
438         result, m_CodeModifierSeq, m_Modifiers, getData(), getRules()->getByTag(m_CodeModifierSeq));
439     if (result.good())
440     {
441         result = CodeSequenceMacro::write(destination);
442     }
443     return result;
444 }
445 
~CodeWithModifiers()446 CodeWithModifiers::~CodeWithModifiers()
447 {
448     DcmIODUtil::freeContainer(m_Modifiers);
449 }
450 
toString()451 OFString CodeSequenceMacro::toString()
452 {
453     OFString d, m, v;
454     getCodeValue(v);
455     getCodeMeaning(m);
456     getCodingSchemeDesignator(d);
457     OFStringStream oss;
458     oss << "(" << d << "," << v << "," << m << ")";
459     OFSTRINGSTREAM_GETOFSTRING(oss, msg);
460     return msg;
461 }
462 
463 // ---------------------- SeriesAndInstanceReferenceMacro----------------------
464 
465 const OFString IODSeriesAndInstanceReferenceMacro::m_ComponentName = "SeriesAndInstanceReferenceMacro";
466 const OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::m_ComponentName
467     = "SeriesAndInstanceReferenceMacro";
468 
IODSeriesAndInstanceReferenceMacro(OFshared_ptr<DcmItem> data,OFshared_ptr<IODRules> rules,IODComponent * parent)469 IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(OFshared_ptr<DcmItem> data,
470                                                                        OFshared_ptr<IODRules> rules,
471                                                                        IODComponent* parent)
472     : IODComponent(data, rules, parent)
473     , m_ReferencedSeriesItems()
474 {
475     // reset element rules
476     resetRules();
477 }
478 
IODSeriesAndInstanceReferenceMacro(IODComponent * parent)479 IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(IODComponent* parent)
480     : IODComponent(parent)
481     , m_ReferencedSeriesItems()
482 {
483     // reset element rules
484     resetRules();
485 }
486 
getName() const487 OFString IODSeriesAndInstanceReferenceMacro::getName() const
488 {
489     return m_ComponentName;
490 }
491 
read(DcmItem & source,const OFBool clearOldData)492 OFCondition IODSeriesAndInstanceReferenceMacro::read(DcmItem& source, const OFBool clearOldData)
493 {
494     if (clearOldData)
495         clearData();
496 
497     DcmIODUtil::readSubSequence<OFVector<ReferencedSeriesItem*> >(
498         source, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence));
499     return EC_Normal;
500 }
501 
write(DcmItem & destination)502 OFCondition IODSeriesAndInstanceReferenceMacro::write(DcmItem& destination)
503 {
504     OFCondition result = EC_Normal;
505 
506     DcmIODUtil::writeSubSequence<OFVector<ReferencedSeriesItem*> >(result,
507                                                                    DCM_ReferencedSeriesSequence,
508                                                                    m_ReferencedSeriesItems,
509                                                                    destination,
510                                                                    m_Rules->getByTag(DCM_ReferencedSeriesSequence));
511 
512     return result;
513 }
514 
clearData()515 void IODSeriesAndInstanceReferenceMacro::clearData()
516 {
517     DcmIODUtil::freeContainer(m_ReferencedSeriesItems);
518 }
519 
resetRules()520 void IODSeriesAndInstanceReferenceMacro::resetRules()
521 {
522     m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE),
523                      OFTrue);
524 }
525 
526 OFVector<IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem*>&
getReferencedSeriesItems()527 IODSeriesAndInstanceReferenceMacro::getReferencedSeriesItems()
528 {
529     return m_ReferencedSeriesItems;
530 }
531 
~IODSeriesAndInstanceReferenceMacro()532 IODSeriesAndInstanceReferenceMacro::~IODSeriesAndInstanceReferenceMacro()
533 {
534     DcmIODUtil::freeContainer(m_ReferencedSeriesItems);
535 }
536 
ReferencedSeriesItem(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent)537 IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(OFshared_ptr<DcmItem> item,
538                                                                                OFshared_ptr<IODRules> rules,
539                                                                                IODComponent* parent)
540     : IODComponent(item, rules, parent)
541     , m_ReferencedInstanceSequence()
542 {
543     // reset element rules
544     resetRules();
545 }
546 
ReferencedSeriesItem(IODComponent * parent)547 IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(IODComponent* parent)
548     : IODComponent(parent)
549     , m_ReferencedInstanceSequence()
550 {
551     // reset element rules
552     resetRules();
553 }
554 
~ReferencedSeriesItem()555 IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::~ReferencedSeriesItem()
556 {
557     clearData();
558 }
559 
getName() const560 OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getName() const
561 {
562     return m_ComponentName;
563 }
564 
clearData()565 void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::clearData()
566 {
567     DcmIODUtil::freeContainer(m_ReferencedInstanceSequence);
568     IODComponent::clearData();
569 }
570 
read(DcmItem & source,const OFBool clearOldData)571 OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::read(DcmItem& source, const OFBool clearOldData)
572 {
573     if (clearOldData)
574         clearData();
575 
576     IODComponent::read(source, clearOldData);
577     DcmIODUtil::readSubSequence(source,
578                                 DCM_ReferencedInstanceSequence,
579                                 m_ReferencedInstanceSequence,
580                                 m_Rules->getByTag(DCM_ReferencedInstanceSequence));
581     return EC_Normal;
582 }
583 
write(DcmItem & destination)584 OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::write(DcmItem& destination)
585 {
586     OFCondition result = EC_Normal;
587 
588     DcmIODUtil::writeSubSequence<OFVector<SOPInstanceReferenceMacro*> >(
589         result,
590         DCM_ReferencedInstanceSequence,
591         m_ReferencedInstanceSequence,
592         *m_Item,
593         m_Rules->getByTag(DCM_ReferencedInstanceSequence));
594     result = IODComponent::write(destination);
595 
596     return result;
597 }
598 
resetRules()599 void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::resetRules()
600 {
601     // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level
602     m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
603     m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE),
604                      OFTrue);
605 }
606 
607 OFVector<SOPInstanceReferenceMacro*>&
getReferencedInstanceItems()608 IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getReferencedInstanceItems()
609 {
610     return m_ReferencedInstanceSequence;
611 }
612 
613 OFCondition
getSeriesInstanceUID(OFString & value,const long signed int pos) const614 IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getSeriesInstanceUID(OFString& value,
615                                                                                const long signed int pos) const
616 {
617     return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos);
618 }
619 
setSeriesInstanceUID(const OFString & value,const OFBool checkValue)620 OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::setSeriesInstanceUID(const OFString& value,
621                                                                                            const OFBool checkValue)
622 {
623     OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal;
624     if (result.good())
625         result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value);
626     return result;
627 }
628 
addReference(const OFString & sopClassUID,const OFString & sopInstanceUID)629 OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::addReference(const OFString& sopClassUID,
630                                                                                    const OFString& sopInstanceUID)
631 {
632     OFVector<SOPInstanceReferenceMacro*>::iterator instance = m_ReferencedInstanceSequence.begin();
633     while (instance != m_ReferencedInstanceSequence.end())
634     {
635         OFString c, i;
636         (*instance)->getReferencedSOPClassUID(c);
637         (*instance)->getReferencedSOPInstanceUID(i);
638         if (i == sopInstanceUID)
639         {
640             DCMIOD_DEBUG("Skipping doubled instance reference when adding to Series and Instance Reference Macro");
641             return EC_Normal;
642         }
643         else
644         {
645             instance++;
646         }
647     }
648     // We get here in case that we do not have this reference, add new one
649     SOPInstanceReferenceMacro* macro = new SOPInstanceReferenceMacro();
650     if (!macro)
651     {
652         return EC_MemoryExhausted;
653     }
654     OFCondition result = macro->setReferencedSOPClassUID(sopClassUID);
655     if (result.good())
656         result = macro->setReferencedSOPInstanceUID(sopInstanceUID);
657     if (result.good())
658     {
659         m_ReferencedInstanceSequence.push_back(macro);
660     }
661     else
662     {
663         delete macro;
664         result = IOD_EC_InvalidElementValue;
665     }
666     return result;
667 }
668 
669 // ---------------------- SOPInstanceReferenceMacro ----------------------
670 
SOPInstanceReferenceMacro(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent)671 SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(OFshared_ptr<DcmItem> item,
672                                                      OFshared_ptr<IODRules> rules,
673                                                      IODComponent* parent)
674     : IODComponent(item, rules, parent)
675 {
676     // reset element rules
677     resetRules();
678 }
679 
SOPInstanceReferenceMacro(IODComponent * parent)680 SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(IODComponent* parent)
681     : IODComponent(parent)
682 {
683     // reset element rules
684     resetRules();
685 }
686 
~SOPInstanceReferenceMacro()687 SOPInstanceReferenceMacro::~SOPInstanceReferenceMacro()
688 {
689     // nothing to do
690 }
691 
getName() const692 OFString SOPInstanceReferenceMacro::getName() const
693 {
694     return "SOPInstanceReferenceMacro";
695 }
696 
resetRules()697 void SOPInstanceReferenceMacro::resetRules()
698 {
699     // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level
700     m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue);
701     m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue);
702 }
703 
704 // -- get dicom attributes --
705 
getReferencedSOPClassUID(OFString & value,const signed long pos)706 OFCondition SOPInstanceReferenceMacro::getReferencedSOPClassUID(OFString& value, const signed long pos)
707 {
708     return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *m_Item, value, pos);
709 }
710 
getReferencedSOPInstanceUID(OFString & value,const signed long pos)711 OFCondition SOPInstanceReferenceMacro::getReferencedSOPInstanceUID(OFString& value, const signed long pos)
712 {
713     return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *m_Item, value, pos);
714 }
715 
716 // -- set dicom attributes --
717 
setReferencedSOPClassUID(const OFString & value,const OFBool checkValue)718 OFCondition SOPInstanceReferenceMacro::setReferencedSOPClassUID(const OFString& value, const OFBool checkValue)
719 {
720     OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal;
721     if (result.good())
722         result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value);
723     return result;
724 }
725 
setReferencedSOPInstanceUID(const OFString & value,const OFBool checkValue)726 OFCondition SOPInstanceReferenceMacro::setReferencedSOPInstanceUID(const OFString& value, const OFBool checkValue)
727 {
728     OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal;
729     if (result.good())
730         result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value);
731     return result;
732 }
733 
734 // ---------------------- ImageSOPInstanceReferenceMacro ----------------------
735 
ImageSOPInstanceReferenceMacro()736 ImageSOPInstanceReferenceMacro::ImageSOPInstanceReferenceMacro()
737     : ReferencedFrameNumber(DCM_ReferencedFrameNumber)
738     , ReferencedSegmentNumber(DCM_ReferencedSegmentNumber)
739 {
740 }
741 
create(const OFString & sopClassUID,const OFString & sopInstanceUID,ImageSOPInstanceReferenceMacro * & result)742 OFCondition ImageSOPInstanceReferenceMacro::create(const OFString& sopClassUID,
743                                                    const OFString& sopInstanceUID,
744                                                    ImageSOPInstanceReferenceMacro*& result)
745 {
746     result = new ImageSOPInstanceReferenceMacro();
747     if (!result)
748         return EC_MemoryExhausted;
749 
750     OFCondition cond = result->setReferencedSOPClassUID(sopClassUID);
751     if (cond.good())
752     {
753         cond = result->setReferencedSOPInstanceUID(sopInstanceUID);
754     }
755     if (cond.bad())
756     {
757         delete result;
758         result = NULL;
759     }
760     return cond;
761 }
762 
create(const OFString & sopClassUID,const OFString & sopInstanceUID,const OFVector<Uint16> & refFramesOrSegments,ImageSOPInstanceReferenceMacro * & result)763 OFCondition ImageSOPInstanceReferenceMacro::create(const OFString& sopClassUID,
764                                                    const OFString& sopInstanceUID,
765                                                    const OFVector<Uint16>& refFramesOrSegments,
766                                                    ImageSOPInstanceReferenceMacro*& result)
767 {
768     OFCondition cond = create(sopClassUID, sopInstanceUID, result);
769     if (cond.good())
770     {
771         if (!refFramesOrSegments.empty())
772         {
773             if (sopClassUID == UID_SegmentationStorage)
774             {
775                 cond = result->setReferencedSegmentNumber(refFramesOrSegments);
776             }
777             else
778             {
779                 cond = result->setReferencedFrameNumber(refFramesOrSegments);
780             }
781         }
782         if (cond.bad())
783         {
784             delete result;
785             result = NULL;
786         }
787     }
788     return cond;
789 }
790 
~ImageSOPInstanceReferenceMacro()791 ImageSOPInstanceReferenceMacro::~ImageSOPInstanceReferenceMacro()
792 {
793 }
794 
compare(const IODComponent & rhs) const795 int ImageSOPInstanceReferenceMacro::compare(const IODComponent& rhs) const
796 {
797     const ImageSOPInstanceReferenceMacro* macro = OFstatic_cast(const ImageSOPInstanceReferenceMacro*, &rhs);
798     if (macro == NULL)
799         return -1;
800     int result = ReferencedFrameNumber.compare(macro->ReferencedFrameNumber);
801     if (result == 0)
802         ReferencedSegmentNumber.compare(macro->ReferencedSegmentNumber);
803     if (result == 0)
804         return SOPInstanceReferenceMacro::compare(rhs);
805     return result;
806 }
807 
clear()808 void ImageSOPInstanceReferenceMacro::clear()
809 {
810     SOPInstanceReferenceMacro::clearData();
811     ReferencedFrameNumber.clear();
812     ReferencedSegmentNumber.clear();
813 }
814 
read(DcmItem & source,const OFBool clearOldData)815 OFCondition ImageSOPInstanceReferenceMacro::read(DcmItem& source, const OFBool clearOldData)
816 {
817     /* re-initialize object */
818     if (clearOldData)
819         clear();
820 
821     OFCondition result = SOPInstanceReferenceMacro::read(source, clearOldData);
822 
823     DcmIODUtil::getAndCheckElementFromDataset(
824         source, ReferencedFrameNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro");
825     DcmIODUtil::getAndCheckElementFromDataset(
826         source, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro");
827 
828     return result;
829 }
830 
write(DcmItem & item)831 OFCondition ImageSOPInstanceReferenceMacro::write(DcmItem& item)
832 {
833     OFCondition result = EC_Normal;
834     /* copy all elements to dataset */
835     DcmIODUtil::copyElementToDataset(
836         result, item, ReferencedFrameNumber, "1-n" /* VM */, "1C" /* Type */, "ImageSOPInstanceReferenceMacro");
837     DcmIODUtil::copyElementToDataset(
838         result, item, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro");
839 
840     if (result.good())
841         result = SOPInstanceReferenceMacro::write(item);
842 
843     return result;
844 }
845 
846 // -- get dicom attributes --
847 
getReferencedFrameNumber(OFVector<Uint16> & values)848 OFCondition ImageSOPInstanceReferenceMacro::getReferencedFrameNumber(OFVector<Uint16>& values)
849 {
850     // cast away const since underlying dcmdata routine is not const...
851     DcmIntegerString* is = OFconst_cast(DcmIntegerString*, &ReferencedFrameNumber);
852     for (size_t n = 0; n < is->getNumberOfValues(); n++)
853     {
854         Sint32 sint = 0;
855         is->getSint32(sint, OFstatic_cast(unsigned long, n));
856         if (sint < 0)
857         {
858             DCMIOD_WARN("Invalid Referenced Frame Number in Image SOP Instance Reference Macro: " << sint);
859             return EC_CorruptedData;
860         }
861         values.push_back(OFstatic_cast(Uint16, sint));
862     }
863     return EC_Normal;
864 }
865 
getReferencedSegmentNumber(OFVector<Uint16> & values)866 OFCondition ImageSOPInstanceReferenceMacro::getReferencedSegmentNumber(OFVector<Uint16>& values)
867 {
868     // cast away const since underlying dcmdata routine is not const...
869     DcmUnsignedShort* us = OFconst_cast(DcmUnsignedShort*, &ReferencedSegmentNumber);
870     return DcmIODUtil::getUint16ValuesFromElement(*us, values);
871 }
872 
873 // -- set dicom attributes --
874 
setReferencedFrameNumber(const OFVector<Uint16> & values,const OFBool checkValue)875 OFCondition ImageSOPInstanceReferenceMacro::setReferencedFrameNumber(const OFVector<Uint16>& values,
876                                                                      const OFBool checkValue)
877 {
878     return DcmIODUtil::setUint16ValuesOnElement(ReferencedFrameNumber, values, "1-n", checkValue);
879 }
880 
addReferencedFrameNumber(const Uint16 & value,const OFBool checkValue)881 OFCondition ImageSOPInstanceReferenceMacro::addReferencedFrameNumber(const Uint16& value, const OFBool checkValue)
882 {
883     (void)checkValue;
884     OFString val;
885     ReferencedFrameNumber.getOFStringArray(val);
886     if (ReferencedFrameNumber.getNumberOfValues() > 0)
887     {
888         val += "\\";
889     }
890     char buf[10];
891     sprintf(buf, "%u", value);
892     val += buf;
893     return ReferencedFrameNumber.putOFStringArray(val);
894 }
895 
setReferencedSegmentNumber(const OFVector<Uint16> & values,const OFBool checkValue)896 OFCondition ImageSOPInstanceReferenceMacro::setReferencedSegmentNumber(const OFVector<Uint16>& values,
897                                                                        const OFBool checkValue)
898 {
899     return DcmIODUtil::setUint16ValuesOnElement(ReferencedSegmentNumber, values, "1-n", checkValue);
900 }
901 
addReferencedSegmentNumber(const Uint16 & value,const OFBool checkValue)902 OFCondition ImageSOPInstanceReferenceMacro::addReferencedSegmentNumber(const Uint16& value, const OFBool checkValue)
903 {
904     (void)checkValue;
905     const unsigned long count = ReferencedSegmentNumber.getNumberOfValues();
906     return ReferencedSegmentNumber.putUint16(value, count /* starts with 0, so add new value at the end */);
907 }
908 
909 // ---------------------- GeneralAnatomyMacro ----------------------
910 
GeneralAnatomyMacro(const OFString & type)911 GeneralAnatomyMacro::GeneralAnatomyMacro(const OFString& type)
912     : m_Type(type)
913     , m_AnatomicRegion()
914     , m_AnatomicRegionModifier()
915     , m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */,
916                                  "1",
917                                  DCM_PrimaryAnatomicStructureModifierSequence)
918 {
919     m_Type = type;
920 }
921 
GeneralAnatomyMacro(const GeneralAnatomyMacro & rhs)922 GeneralAnatomyMacro::GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs)
923     : m_Type(rhs.m_Type)
924     , m_AnatomicRegion()
925     , m_AnatomicRegionModifier()
926     , m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */,
927                                  "1",
928                                  DCM_PrimaryAnatomicStructureModifierSequence)
929 {
930     *this = rhs;
931 }
932 
operator =(const GeneralAnatomyMacro & rhs)933 GeneralAnatomyMacro& GeneralAnatomyMacro::operator=(const GeneralAnatomyMacro& rhs)
934 {
935     if (this != &rhs)
936     {
937         clearData();
938         m_Type                     = rhs.m_Type;
939         m_AnatomicRegion           = rhs.m_AnatomicRegion;
940         m_PrimaryAnatomicStructure = rhs.m_PrimaryAnatomicStructure;
941 
942         OFVector<CodeSequenceMacro*>::const_iterator it = rhs.m_AnatomicRegionModifier.begin();
943         while (it != rhs.m_AnatomicRegionModifier.end())
944         {
945             m_AnatomicRegionModifier.push_back(new CodeSequenceMacro(**it));
946             it++;
947         }
948     }
949     return *this;
950 }
951 
~GeneralAnatomyMacro()952 GeneralAnatomyMacro::~GeneralAnatomyMacro()
953 {
954     clearData();
955 }
956 
clearData()957 void GeneralAnatomyMacro::clearData()
958 {
959     // m_Type stays the same
960     m_AnatomicRegion.clearData();
961     DcmIODUtil::freeContainer(m_AnatomicRegionModifier);
962     m_PrimaryAnatomicStructure.clearData();
963 }
964 
check(const OFBool quiet)965 OFCondition GeneralAnatomyMacro::check(const OFBool quiet)
966 {
967     OFCondition result = m_AnatomicRegion.check(quiet);
968     if (result.bad())
969         return result;
970 
971     OFVector<CodeSequenceMacro*>::iterator it = m_AnatomicRegionModifier.begin();
972     while (it != m_AnatomicRegionModifier.begin())
973     {
974         result = (*it)->check(quiet);
975         if (result.bad())
976             return result;
977         it++;
978     }
979     // Primary Anatomic Structure is optional (type 3), so only check if
980     // user intended to fill in something.
981     if (!m_PrimaryAnatomicStructure.empty())
982     {
983         result = m_PrimaryAnatomicStructure.check(quiet);
984     }
985     return result;
986 }
987 
getAnatomicRegion()988 CodeSequenceMacro& GeneralAnatomyMacro::getAnatomicRegion()
989 {
990     return m_AnatomicRegion;
991 }
992 
getAnatomicRegionModifier()993 OFVector<CodeSequenceMacro*>& GeneralAnatomyMacro::getAnatomicRegionModifier()
994 {
995     return m_AnatomicRegionModifier;
996 }
997 
getPrimaryAnatomicStructure()998 PrimaryAnatomicStructureMacro& GeneralAnatomyMacro::getPrimaryAnatomicStructure()
999 {
1000     return m_PrimaryAnatomicStructure;
1001 }
1002 
1003 // Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item
read(DcmItem & source,const OFBool clearOldData)1004 OFCondition GeneralAnatomyMacro::read(DcmItem& source, const OFBool clearOldData)
1005 {
1006     OFCondition result = EC_Normal;
1007 
1008     /* re-initialize object */
1009     if (clearOldData)
1010         clearData();
1011 
1012     /* read Anatomic Region Sequence item into Code Sequence Macro */
1013     DcmIODUtil::readSingleItem<CodeSequenceMacro>(
1014         source, DCM_AnatomicRegionSequence, m_AnatomicRegion, m_Type, "GeneralAnatomyMacro");
1015 
1016     /* read Primary Anatomic Structure Macro (main level, i.e.\ original item) */
1017     DcmIODUtil::readSingleItem(
1018         source, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, "3", "GeneralAnatomyMacro");
1019 
1020     /* Get the single item from Anatomic Region Sequence and read modifier if found */
1021     DcmItem* localItem = NULL;
1022     if (source.findAndGetSequenceItem(DCM_AnatomicRegionSequence, localItem).bad())
1023     {
1024         return result;
1025     }
1026 
1027     /* read Anatomic Region Modifier Sequence from */
1028     DcmIODUtil::readSubSequence<OFVector<CodeSequenceMacro*> >(*localItem, /* item of Anatomic Region Sequence */
1029                                                                DCM_AnatomicRegionModifierSequence,
1030                                                                m_AnatomicRegionModifier,
1031                                                                "1-n",
1032                                                                "3",
1033                                                                "GeneralAnatomyMacro");
1034 
1035     return result;
1036 }
1037 
1038 /// Write Anatomic Region Sequence from given item
write(DcmItem & item)1039 OFCondition GeneralAnatomyMacro::write(DcmItem& item)
1040 {
1041     OFCondition result = EC_Normal;
1042 
1043     /* delete old data */
1044     item.findAndDeleteElement(DCM_AnatomicRegionSequence);
1045     item.findAndDeleteElement(DCM_PrimaryAnatomicStructureSequence);
1046 
1047     /* Write sub structures */
1048     DcmIODUtil::writeSingleItem<CodeSequenceMacro>(
1049         result, DCM_AnatomicRegionSequence, m_AnatomicRegion, item, m_Type, "GeneralAnatomyMacro");
1050     if (result.good())
1051     {
1052         DcmItem* seqItem = NULL;
1053         result           = item.findAndGetSequenceItem(DCM_AnatomicRegionSequence, seqItem, 0);
1054         if (result.good())
1055         {
1056             DcmIODUtil::writeSubSequence<OFVector<CodeSequenceMacro*> >(result,
1057                                                                         DCM_AnatomicRegionModifierSequence,
1058                                                                         m_AnatomicRegionModifier,
1059                                                                         *seqItem,
1060                                                                         "1-n",
1061                                                                         "3",
1062                                                                         "GeneralAnatomyMacro");
1063         }
1064     }
1065     DcmIODUtil::writeSingleItem(
1066         result, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, item, "3", "GeneralAnatomyMacro");
1067     return result;
1068 }
1069 
compare(const GeneralAnatomyMacro & rhs) const1070 int GeneralAnatomyMacro::compare(const GeneralAnatomyMacro& rhs) const
1071 {
1072     int result = m_AnatomicRegion.compare(rhs.m_AnatomicRegion);
1073     if (result == 0)
1074     {
1075         if (m_AnatomicRegionModifier.size() > rhs.m_AnatomicRegionModifier.size())
1076         {
1077             return 1;
1078         }
1079         else if (m_AnatomicRegionModifier.size() < rhs.m_AnatomicRegionModifier.size())
1080         {
1081             return -1;
1082         }
1083 
1084         for (size_t m = 0; m < m_AnatomicRegionModifier.size(); m++)
1085         {
1086             result = m_AnatomicRegionModifier[m]->compare(*(rhs.m_AnatomicRegionModifier[m]));
1087             if (result != 0)
1088             {
1089                 return result;
1090             }
1091         }
1092         result = m_PrimaryAnatomicStructure.compare(rhs.m_PrimaryAnatomicStructure);
1093     }
1094     return result;
1095 }
1096 
1097 // ---------------------- AlgorithmIdentificationMacro ----------------------
1098 
AlgorithmIdentificationMacro()1099 AlgorithmIdentificationMacro::AlgorithmIdentificationMacro()
1100     : m_AlgorithmFamilyCode()
1101     , m_AlgorithmNameCode()
1102     , m_AlgorithmName(DCM_AlgorithmName)
1103     , m_AlgorithmVersion(DCM_AlgorithmVersion)
1104     , m_AlgorithmParameters(DCM_AlgorithmParameters)
1105     , m_AlgorithmSource(DCM_AlgorithmSource)
1106 {
1107 }
1108 //
~AlgorithmIdentificationMacro()1109 AlgorithmIdentificationMacro::~AlgorithmIdentificationMacro()
1110 {
1111     clearData();
1112 }
1113 
clearData()1114 void AlgorithmIdentificationMacro::clearData()
1115 {
1116     m_AlgorithmFamilyCode.clearData();
1117     m_AlgorithmNameCode.clearData();
1118     m_AlgorithmName.clear();
1119     m_AlgorithmVersion.clear();
1120     m_AlgorithmParameters.clear();
1121     m_AlgorithmSource.clear();
1122 }
1123 
check(const OFBool quiet)1124 OFCondition AlgorithmIdentificationMacro::check(const OFBool quiet)
1125 {
1126     OFCondition result;
1127     result = m_AlgorithmFamilyCode.check(quiet);
1128     if (result.good())
1129     {
1130         if (m_AlgorithmName.isEmpty() || m_AlgorithmVersion.isEmpty())
1131         {
1132             result = EC_MissingValue;
1133         }
1134     }
1135     return result;
1136 }
1137 
getAlgorithmFamilyCode()1138 CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmFamilyCode()
1139 {
1140     return m_AlgorithmFamilyCode;
1141 }
1142 
getAlgorithmNameCode()1143 CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmNameCode()
1144 {
1145     return m_AlgorithmNameCode;
1146 }
1147 
getAlgorithmName(OFString & value,const signed long pos)1148 OFCondition AlgorithmIdentificationMacro::getAlgorithmName(OFString& value, const signed long pos)
1149 {
1150     return DcmIODUtil::getStringValueFromElement(m_AlgorithmName, value, pos);
1151 }
1152 
getAlgorithmVersion(OFString & value,const signed long pos)1153 OFCondition AlgorithmIdentificationMacro::getAlgorithmVersion(OFString& value, const signed long pos)
1154 {
1155     return DcmIODUtil::getStringValueFromElement(m_AlgorithmVersion, value, pos);
1156 }
1157 
getAlgorithmParameters(OFString & value,const signed long pos)1158 OFCondition AlgorithmIdentificationMacro::getAlgorithmParameters(OFString& value, const signed long pos)
1159 {
1160     return DcmIODUtil::getStringValueFromElement(m_AlgorithmParameters, value, pos);
1161 }
1162 
getAlgorithmSource(OFString & value,const signed long pos)1163 OFCondition AlgorithmIdentificationMacro::getAlgorithmSource(OFString& value, const signed long pos)
1164 {
1165     return DcmIODUtil::getStringValueFromElement(m_AlgorithmSource, value, pos);
1166 }
1167 
setAlgorithmName(const OFString & value,const OFBool checkValue)1168 OFCondition AlgorithmIdentificationMacro::setAlgorithmName(const OFString& value, const OFBool checkValue)
1169 {
1170     OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
1171     if (result.good())
1172         result = m_AlgorithmName.putOFStringArray(value);
1173     return result;
1174 }
1175 
setAlgorithmVersion(const OFString & value,const OFBool checkValue)1176 OFCondition AlgorithmIdentificationMacro::setAlgorithmVersion(const OFString& value, const OFBool checkValue)
1177 
1178 {
1179     OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
1180     if (result.good())
1181         result = m_AlgorithmVersion.putOFStringArray(value);
1182     return result;
1183 }
1184 
setAlgorithmParameters(const OFString & value,const OFBool checkValue)1185 OFCondition AlgorithmIdentificationMacro::setAlgorithmParameters(const OFString& value, const OFBool checkValue)
1186 {
1187     (void)checkValue;
1188     return m_AlgorithmParameters.putOFStringArray(value);
1189 }
1190 
setAlgorithmSource(const OFString & value,const OFBool checkValue)1191 OFCondition AlgorithmIdentificationMacro::setAlgorithmSource(const OFString& value, const OFBool checkValue)
1192 {
1193     OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
1194     if (result.good())
1195         result = m_AlgorithmSource.putOFStringArray(value);
1196     return result;
1197 }
1198 
1199 /// Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item
read(DcmItem & source,const OFBool clearOldData)1200 OFCondition AlgorithmIdentificationMacro::read(DcmItem& source, const OFBool clearOldData)
1201 {
1202     OFCondition result;
1203 
1204     if (clearOldData)
1205         clearData();
1206 
1207     DcmIODUtil::readSingleItem<CodeSequenceMacro>(
1208         source, DCM_AlgorithmFamilyCodeSequence, m_AlgorithmFamilyCode, "1", "AlgorithmIdentificationMacro");
1209 
1210     DcmIODUtil::readSingleItem<CodeSequenceMacro>(
1211         source, DCM_AlgorithmNameCodeSequence, m_AlgorithmNameCode, "3", "AlgorithmIdentificationMacro");
1212 
1213     DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro");
1214     DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro");
1215     DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro");
1216     DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro");
1217 
1218     return result;
1219 }
1220 
write(DcmItem & item)1221 OFCondition AlgorithmIdentificationMacro::write(DcmItem& item)
1222 {
1223     OFCondition result = EC_Normal;
1224 
1225     // write to item
1226     DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro");
1227     DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro");
1228     DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro");
1229     DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro");
1230 
1231     DcmIODUtil::writeSingleItem<CodeSequenceMacro>(
1232         result, DCM_AlgorithmFamilyCodeSequence, m_AlgorithmFamilyCode, item, "1", "AlgorithmIdentificationMacro");
1233 
1234     DcmIODUtil::writeSingleItem<CodeSequenceMacro>(
1235         result, DCM_AlgorithmNameCodeSequence, m_AlgorithmNameCode, item, "3", "AlgorithmIdentificationMacro");
1236 
1237     return result;
1238 }
1239 
1240 // ---------------------- ContentIdentificationMacro ----------------------
1241 
ContentIdentificationMacro()1242 ContentIdentificationMacro::ContentIdentificationMacro()
1243     : m_InstanceNumber(DCM_InstanceNumber)
1244     , m_ContentLabel(DCM_ContentLabel)
1245     , m_ContentDescription(DCM_ContentDescription)
1246     , m_AlternateContentDescription()
1247     , m_ContentCreatorName(DCM_ContentCreatorName)
1248     , m_ContentCreatorIdentificationCode()
1249     , m_IODRules()
1250 {
1251     resetRules();
1252 }
1253 
ContentIdentificationMacro(const OFString & instanceNumber,const OFString & contentLabel,const OFString & contentDescription,const OFString & contentCreatorName)1254 ContentIdentificationMacro::ContentIdentificationMacro(const OFString& instanceNumber,
1255                                                        const OFString& contentLabel,
1256                                                        const OFString& contentDescription,
1257                                                        const OFString& contentCreatorName)
1258     : m_InstanceNumber(DCM_InstanceNumber)
1259     , m_ContentLabel(DCM_ContentLabel)
1260     , m_ContentDescription(DCM_ContentDescription)
1261     , m_AlternateContentDescription()
1262     , m_ContentCreatorName(DCM_ContentCreatorName)
1263     , m_ContentCreatorIdentificationCode()
1264     , m_IODRules()
1265 {
1266     resetRules();
1267     setInstanceNumber(instanceNumber);
1268     setContentLabel(contentLabel);
1269     setContentDescription(contentDescription);
1270     setContentCreatorName(contentCreatorName);
1271 }
1272 
resetRules()1273 void ContentIdentificationMacro::resetRules()
1274 {
1275     m_IODRules.addRule(new IODRule(DCM_InstanceNumber, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
1276     m_IODRules.addRule(new IODRule(DCM_ContentLabel, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
1277     m_IODRules.addRule(new IODRule(DCM_ContentDescription, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
1278     m_IODRules.addRule(new IODRule(DCM_ContentCreatorName, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
1279     m_IODRules.addRule(
1280         new IODRule(DCM_AlternateContentDescriptionSequence, "1-n", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
1281     m_IODRules.addRule(
1282         new IODRule(DCM_ContentCreatorIdentificationCodeSequence, "1", "3", getName(), DcmIODTypes::IE_INSTANCE),
1283         OFTrue);
1284 }
1285 
getName() const1286 OFString ContentIdentificationMacro::getName() const
1287 {
1288     return "ContentIdentificationMacro";
1289 }
1290 
getIODRules()1291 IODRules& ContentIdentificationMacro::getIODRules()
1292 {
1293     return m_IODRules;
1294 }
1295 
ContentIdentificationMacro(const ContentIdentificationMacro & rhs)1296 ContentIdentificationMacro::ContentIdentificationMacro(const ContentIdentificationMacro& rhs)
1297     : m_InstanceNumber(DCM_InstanceNumber)
1298     , m_ContentLabel(DCM_ContentLabel)
1299     , m_ContentDescription(DCM_ContentDescription)
1300     , m_AlternateContentDescription()
1301     , m_ContentCreatorName(DCM_ContentCreatorName)
1302     , m_ContentCreatorIdentificationCode()
1303     , m_IODRules()
1304 {
1305     if (&rhs != this)
1306     {
1307         resetRules();
1308         m_InstanceNumber                   = rhs.m_InstanceNumber;
1309         m_ContentLabel                     = rhs.m_ContentLabel;
1310         m_ContentDescription               = rhs.m_ContentDescription;
1311         m_ContentCreatorName               = rhs.m_ContentCreatorName;
1312         m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode;
1313         /* perform deep vector copy */
1314         OFVector<AlternateContentDescriptionItem*>::const_iterator it = rhs.m_AlternateContentDescription.begin();
1315         while (it != rhs.m_AlternateContentDescription.end())
1316         {
1317             m_AlternateContentDescription.push_back(new AlternateContentDescriptionItem(**it));
1318             it++;
1319         }
1320     }
1321 }
1322 
create(const OFString & instanceNumber,const OFString & contentLabel,const OFString & contentDescription,const OFString & contentCreatorName,ContentIdentificationMacro * & result)1323 OFCondition ContentIdentificationMacro::create(const OFString& instanceNumber,
1324                                                const OFString& contentLabel,
1325                                                const OFString& contentDescription,
1326                                                const OFString& contentCreatorName,
1327                                                ContentIdentificationMacro*& result)
1328 {
1329     result = new ContentIdentificationMacro();
1330     if (!result)
1331         return EC_MemoryExhausted;
1332     OFCondition cond = result->setInstanceNumber(instanceNumber);
1333     if (cond.good())
1334     {
1335         cond = result->setContentLabel(contentLabel);
1336     }
1337     if (cond.good())
1338     {
1339         cond = result->setContentDescription(contentDescription);
1340     }
1341     if (cond.good())
1342     {
1343         cond = result->setContentCreatorName(contentCreatorName);
1344     }
1345     if (cond.good())
1346     {
1347         cond = result->check();
1348     }
1349     if (cond.bad())
1350     {
1351         delete result;
1352         result = NULL;
1353     }
1354     return cond;
1355 }
1356 
operator =(const ContentIdentificationMacro & rhs)1357 ContentIdentificationMacro& ContentIdentificationMacro::operator=(const ContentIdentificationMacro& rhs)
1358 {
1359     if (&rhs != this)
1360     {
1361         this->clearData();
1362         m_InstanceNumber                   = rhs.m_InstanceNumber;
1363         m_ContentLabel                     = rhs.m_ContentLabel;
1364         m_ContentDescription               = rhs.m_ContentDescription;
1365         m_ContentCreatorName               = rhs.m_ContentCreatorName;
1366         m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode;
1367         /* perform deep vector copy */
1368         OFVector<AlternateContentDescriptionItem*>::const_iterator it = rhs.m_AlternateContentDescription.begin();
1369         while (it != rhs.m_AlternateContentDescription.end())
1370         {
1371             AlternateContentDescriptionItem* newItem = new AlternateContentDescriptionItem();
1372             *newItem                                 = **it;
1373             m_AlternateContentDescription.push_back(newItem);
1374             it++;
1375         }
1376     }
1377     return *this;
1378 }
1379 
~ContentIdentificationMacro()1380 ContentIdentificationMacro::~ContentIdentificationMacro()
1381 {
1382     clearData();
1383 }
1384 
clearData()1385 void ContentIdentificationMacro::clearData()
1386 {
1387     m_InstanceNumber.clear();
1388     m_ContentLabel.clear();
1389     m_ContentDescription.clear();
1390     DcmIODUtil::freeContainer(m_AlternateContentDescription);
1391     m_ContentCreatorName.clear();
1392     m_ContentCreatorIdentificationCode.clearData();
1393 }
1394 
check(const OFBool quiet)1395 OFCondition ContentIdentificationMacro::check(const OFBool quiet)
1396 {
1397     (void)quiet;
1398     OFCondition result;
1399     OFBool failure = m_ContentLabel.isEmpty() || m_InstanceNumber.isEmpty();
1400     if (!failure)
1401     {
1402         if (!m_AlternateContentDescription.empty()) // type 3
1403         {
1404             OFVector<AlternateContentDescriptionItem*>::iterator it = m_AlternateContentDescription.begin();
1405             while (it != m_AlternateContentDescription.end() && !failure)
1406             {
1407                 OFString str;
1408                 (*it)->getContentDescription(str).good(); // type 1
1409                 failure = str.empty();
1410                 if (!failure)
1411                 {
1412                     OFString meaning, value, designator;
1413                     (*it)->getLanguageCode().getCodeMeaning(meaning);
1414                     (*it)->getLanguageCode().getCodeValue(value);
1415                     (*it)->getLanguageCode().getCodeValue(designator);
1416                     failure = meaning.empty() || value.empty() || designator.empty();
1417                 }
1418                 it++;
1419             }
1420         }
1421     }
1422     if (failure)
1423         result = EC_IllegalParameter;
1424     return result;
1425 }
1426 
getInstanceNumber(OFString & value,const signed long pos) const1427 OFCondition ContentIdentificationMacro::getInstanceNumber(OFString& value, const signed long pos) const
1428 {
1429     return DcmIODUtil::getStringValueFromElement(m_InstanceNumber, value, pos);
1430 }
1431 
getContentLabel(OFString & value,const signed long pos) const1432 OFCondition ContentIdentificationMacro::getContentLabel(OFString& value, const signed long pos) const
1433 {
1434     return DcmIODUtil::getStringValueFromElement(m_ContentLabel, value, pos);
1435 }
1436 
getContentDescription(OFString & value,const signed long pos) const1437 OFCondition ContentIdentificationMacro::getContentDescription(OFString& value, const signed long pos) const
1438 {
1439     return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos);
1440 }
1441 
getContentCreatorName(OFString & value,const signed long pos) const1442 OFCondition ContentIdentificationMacro::getContentCreatorName(OFString& value, const signed long pos) const
1443 {
1444     return DcmIODUtil::getStringValueFromElement(m_ContentCreatorName, value, pos);
1445 }
1446 
getContentCreatorIdentificationCode()1447 CodeSequenceMacro& ContentIdentificationMacro::getContentCreatorIdentificationCode()
1448 {
1449     return m_ContentCreatorIdentificationCode;
1450 }
1451 
1452 OFVector<ContentIdentificationMacro::AlternateContentDescriptionItem*>&
getAlternateContentDescription()1453 ContentIdentificationMacro::getAlternateContentDescription()
1454 {
1455     return m_AlternateContentDescription;
1456 }
1457 
setInstanceNumber(const OFString & value,const OFBool checkValue)1458 OFCondition ContentIdentificationMacro::setInstanceNumber(const OFString& value, const OFBool checkValue)
1459 {
1460     OFCondition result;
1461     if (checkValue)
1462     {
1463         result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal;
1464     }
1465     if (result.good())
1466     {
1467         result = m_InstanceNumber.putOFStringArray(value);
1468     }
1469     return result;
1470 }
1471 
setContentLabel(const OFString & value,const OFBool checkValue)1472 OFCondition ContentIdentificationMacro::setContentLabel(const OFString& value, const OFBool checkValue)
1473 {
1474     OFCondition result = (checkValue)
1475         ? DcmCodeString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentLabel)->getVM())
1476         : EC_Normal;
1477     if (result.good())
1478         result = m_ContentLabel.putOFStringArray(value);
1479     return result;
1480 }
1481 
setContentDescription(const OFString & value,const OFBool checkValue)1482 OFCondition ContentIdentificationMacro::setContentDescription(const OFString& value, const OFBool checkValue)
1483 {
1484     OFCondition result = (checkValue)
1485         ? DcmLongString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentDescription)->getVM())
1486         : EC_Normal;
1487     if (result.good())
1488         result = m_ContentDescription.putOFStringArray(value);
1489     return result;
1490 }
1491 
setContentCreatorName(const OFString & value,const OFBool checkValue)1492 OFCondition ContentIdentificationMacro::setContentCreatorName(const OFString& value, const OFBool checkValue)
1493 {
1494     OFCondition result = (checkValue)
1495         ? DcmPersonName::checkStringValue(value, m_IODRules.getByTag(DCM_ContentCreatorName)->getVM())
1496         : EC_Normal;
1497     if (result.good())
1498         result = m_ContentCreatorName.putOFStringArray(value);
1499     return result;
1500 }
1501 
read(DcmItem & source,const OFBool clearOldData)1502 OFCondition ContentIdentificationMacro::read(DcmItem& source, const OFBool clearOldData)
1503 {
1504     OFCondition result;
1505 
1506     if (clearOldData)
1507         clearData();
1508 
1509     /* flat elements */
1510 
1511     DcmIODUtil::getAndCheckElementFromDataset(source, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber));
1512     DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel));
1513     DcmIODUtil::getAndCheckElementFromDataset(
1514         source, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription));
1515     DcmIODUtil::getAndCheckElementFromDataset(
1516         source, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName));
1517 
1518     /* sub sequences */
1519     IODRule* rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence);
1520     DcmIODUtil::readSubSequence<OFVector<AlternateContentDescriptionItem*> >(source,
1521                                                                              DCM_AlternateContentDescriptionSequence,
1522                                                                              m_AlternateContentDescription,
1523                                                                              rule->getVM(),
1524                                                                              rule->getType(),
1525                                                                              "ContentIdentificationMacro");
1526 
1527     rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence);
1528     DcmIODUtil::readSingleItem<CodeSequenceMacro>(source,
1529                                                   DCM_ContentCreatorIdentificationCodeSequence,
1530                                                   m_ContentCreatorIdentificationCode,
1531                                                   rule->getType(),
1532                                                   "ContentIdentificationMacro");
1533 
1534     return result;
1535 }
1536 
write(DcmItem & item)1537 OFCondition ContentIdentificationMacro::write(DcmItem& item)
1538 {
1539     OFCondition result = EC_Normal;
1540 
1541     /* flat elements */
1542     DcmIODUtil::copyElementToDataset(result, item, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber));
1543     DcmIODUtil::copyElementToDataset(result, item, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel));
1544     DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription));
1545     DcmIODUtil::copyElementToDataset(result, item, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName));
1546 
1547     IODRule* rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence);
1548     DcmIODUtil::writeSingleItem<CodeSequenceMacro>(result,
1549                                                    DCM_ContentCreatorIdentificationCodeSequence,
1550                                                    m_ContentCreatorIdentificationCode,
1551                                                    item,
1552                                                    rule->getType(),
1553                                                    "ContentIdentificationMacro");
1554 
1555     rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence);
1556     DcmIODUtil::writeSubSequence<OFVector<ContentIdentificationMacro::AlternateContentDescriptionItem*> >(
1557         result,
1558         DCM_AlternateContentDescriptionSequence,
1559         m_AlternateContentDescription,
1560         item,
1561         rule->getVM(),
1562         rule->getType(),
1563         "ContentIdentificationMacro");
1564 
1565     return result;
1566 }
1567 
1568 // ---------------- ContentIdentificationMacro::AlternateContentDescriptionItem -----------------
1569 
AlternateContentDescriptionItem()1570 ContentIdentificationMacro::AlternateContentDescriptionItem::AlternateContentDescriptionItem()
1571     : m_ContentDescription(DCM_ContentDescription)
1572     , m_LanguageCode()
1573 {
1574     // nothing to do
1575 }
1576 
~AlternateContentDescriptionItem()1577 ContentIdentificationMacro::AlternateContentDescriptionItem::~AlternateContentDescriptionItem()
1578 {
1579     m_LanguageCode.clearData();
1580 }
1581 
clearData()1582 void ContentIdentificationMacro::AlternateContentDescriptionItem::clearData()
1583 {
1584     m_ContentDescription.clear();
1585     m_LanguageCode.clearData();
1586 }
1587 
read(DcmItem & source,const OFBool clearOldData)1588 OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::read(DcmItem& source,
1589                                                                               const OFBool clearOldData)
1590 {
1591     OFCondition result;
1592     if (clearOldData)
1593         clearData();
1594 
1595     DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, "1", "1", "ContentIdentificationMacro");
1596     DcmIODUtil::readSingleItem<CodeSequenceMacro>(
1597         source, DCM_LanguageCodeSequence, m_LanguageCode, "1", "ContentIdentificationMacro");
1598 
1599     return result;
1600 }
1601 
1602 OFCondition
getContentDescription(OFString & value,const long signed int pos)1603 ContentIdentificationMacro::AlternateContentDescriptionItem::getContentDescription(OFString& value,
1604                                                                                    const long signed int pos)
1605 {
1606     return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos);
1607 }
1608 
getLanguageCode()1609 CodeSequenceMacro& ContentIdentificationMacro::AlternateContentDescriptionItem::getLanguageCode()
1610 {
1611     return m_LanguageCode;
1612 }
1613 
write(DcmItem & item)1614 OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::write(DcmItem& item)
1615 {
1616     OFCondition result = EC_Normal;
1617     // write to item
1618     DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, "1", "1", "ContentIdentificationMacro");
1619     DcmIODUtil::writeSingleItem<CodeSequenceMacro>(
1620         result, DCM_LanguageCodeSequence, m_LanguageCode, item, "1", "ContentIdentificationMacro");
1621     return result;
1622 }
1623 
setContentDescription(const OFString & value,const OFBool checkValue)1624 OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::setContentDescription(const OFString& value,
1625                                                                                                const OFBool checkValue)
1626 {
1627     OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
1628     if (result.good())
1629         result = m_ContentDescription.putOFStringArray(value);
1630     return result;
1631 }
1632 
1633 // -------------------- HL7HierarchicDesignatorMacro --------------------
1634 
HL7HierarchicDesignatorMacro(IODComponent * parent)1635 HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(IODComponent* parent)
1636     : IODComponent(parent)
1637 {
1638     // reset element rules
1639     resetRules();
1640 }
1641 
HL7HierarchicDesignatorMacro(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent)1642 HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(OFshared_ptr<DcmItem> item,
1643                                                            OFshared_ptr<IODRules> rules,
1644                                                            IODComponent* parent)
1645     : IODComponent(item, rules, parent)
1646 {
1647     // reset element rules
1648     resetRules();
1649 }
1650 
getUniversalEntityID(OFString & value,const long signed int pos) const1651 OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityID(OFString& value, const long signed int pos) const
1652 {
1653     return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityID, *m_Item, value, pos);
1654 }
1655 
getLocalNamespaceEntityID(OFString & value,const long signed int pos) const1656 OFCondition HL7HierarchicDesignatorMacro::getLocalNamespaceEntityID(OFString& value, const long signed int pos) const
1657 {
1658     return DcmIODUtil::getStringValueFromItem(DCM_LocalNamespaceEntityID, *m_Item, value, pos);
1659 }
1660 
getUniversalEntityIDType(OFString & value,const long signed int pos) const1661 OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityIDType(OFString& value, const long signed int pos) const
1662 {
1663     return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityIDType, *m_Item, value, pos);
1664 }
1665 
getName() const1666 OFString HL7HierarchicDesignatorMacro::getName() const
1667 {
1668     return "HL7HierarchicDesignatorMacro";
1669 }
1670 
resetRules()1671 void HL7HierarchicDesignatorMacro::resetRules()
1672 {
1673     // parameters are tag, VM, type. Overwrite old rules if any.
1674     m_Rules->addRule(new IODRule(DCM_UniversalEntityID, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue);
1675     m_Rules->addRule(new IODRule(DCM_LocalNamespaceEntityID, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED),
1676                      OFTrue);
1677     m_Rules->addRule(new IODRule(DCM_UniversalEntityIDType, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue);
1678 }
1679 
setLocalNamespaceEntityID(const OFString & value,const OFBool checkValue)1680 OFCondition HL7HierarchicDesignatorMacro::setLocalNamespaceEntityID(const OFString& value, const OFBool checkValue)
1681 {
1682     (void)checkValue;
1683     return m_Item->putAndInsertOFStringArray(DCM_LocalNamespaceEntityID, value);
1684 }
1685 
setUniversalEntityID(const OFString & value,const OFBool checkValue)1686 OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityID(const OFString& value, const OFBool checkValue)
1687 {
1688     (void)checkValue;
1689     return m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID, value);
1690 }
1691 
setUniversalEntityIDType(const OFString & value,const OFBool checkValue)1692 OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityIDType(const OFString& value, const OFBool checkValue)
1693 {
1694     OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal;
1695     if (result.good())
1696         result = m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID, value);
1697     return result;
1698 }
1699 
1700 // -------------------- Mandatory View and Slice Progression Direction Macro --------------------
1701 
MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr<DcmItem> item,OFshared_ptr<IODRules> rules,IODComponent * parent)1702 MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(
1703     OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules, IODComponent* parent)
1704     : IODComponent(item, rules, parent)
1705     , m_ViewCodeSequence()
1706     , m_ViewModifierCode()
1707 {
1708     resetRules();
1709 }
1710 
MandatoryViewAndSliceProgressionDirectionMacro(IODComponent * parent)1711 MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent)
1712     : IODComponent(parent)
1713     , m_ViewCodeSequence()
1714     , m_ViewModifierCode()
1715 {
1716     resetRules();
1717 }
1718 
getName() const1719 OFString MandatoryViewAndSliceProgressionDirectionMacro::getName() const
1720 {
1721     return "MandatoryViewAndSliceProgressionDirectionMacro";
1722 }
1723 
resetRules()1724 void MandatoryViewAndSliceProgressionDirectionMacro::resetRules()
1725 {
1726     m_Rules->addRule(new IODRule(DCM_ViewCodeSequence, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue);
1727     m_Rules->addRule(new IODRule(DCM_ViewModifierCodeSequence, "1-n", "2C", getName(), DcmIODTypes::IE_UNDEFINED),
1728                      OFTrue);
1729     m_Rules->addRule(new IODRule(DCM_SliceProgressionDirection, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED),
1730                      OFTrue);
1731 }
1732 
clearData()1733 void MandatoryViewAndSliceProgressionDirectionMacro::clearData()
1734 {
1735     DcmIODUtil::freeContainer(m_ViewModifierCode);
1736     m_ViewCodeSequence.clearData();
1737     IODComponent::clearData();
1738 }
1739 
read(DcmItem & source,const OFBool clearOldData)1740 OFCondition MandatoryViewAndSliceProgressionDirectionMacro::read(DcmItem& source, const OFBool clearOldData)
1741 {
1742     if (clearOldData)
1743     {
1744         m_ViewCodeSequence.clearData();
1745         DcmIODUtil::freeContainer(m_ViewModifierCode);
1746     }
1747     OFCondition result = EC_Normal;
1748     DcmIODUtil::readSingleItem(
1749         source, DCM_ViewCodeSequence, m_ViewCodeSequence, m_Rules->getByTag(DCM_ViewCodeSequence));
1750     DcmIODUtil::readSubSequence(
1751         source, DCM_ViewCodeSequence, m_ViewModifierCode, m_Rules->getByTag(DCM_ViewCodeSequence));
1752     IODComponent::read(source, clearOldData);
1753     return EC_Normal;
1754 }
1755 
write(DcmItem & item)1756 OFCondition MandatoryViewAndSliceProgressionDirectionMacro::write(DcmItem& item)
1757 {
1758     OFCondition result = EC_Normal;
1759     DcmIODUtil::writeSingleItem(
1760         result, DCM_ViewCodeSequence, m_ViewCodeSequence, *m_Item, m_Rules->getByTag(DCM_ViewCodeSequence));
1761     DcmIODUtil::writeSubSequence(
1762         result, DCM_ViewCodeSequence, m_ViewModifierCode, *m_Item, m_Rules->getByTag(DCM_ViewModifierCodeSequence));
1763     if (result.good())
1764         result = IODComponent::write(item);
1765     return result;
1766 }
1767 
getViewCode()1768 CodeSequenceMacro& MandatoryViewAndSliceProgressionDirectionMacro::getViewCode()
1769 {
1770     return m_ViewCodeSequence;
1771 }
1772 
getViewModifierCode()1773 OFVector<CodeSequenceMacro*>& MandatoryViewAndSliceProgressionDirectionMacro::getViewModifierCode()
1774 {
1775     return m_ViewModifierCode;
1776 }
1777