1 /*
2 *
3 * Copyright (C) 2015-2019, 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: dcmfg
15 *
16 * Author: Michael Onken
17 *
18 * Purpose: Base class(es) for functional groups
19 *
20 */
21
22 #include "dcmtk/config/osconfig.h"
23
24 #include "dcmtk/dcmdata/dcdeftag.h"
25 #include "dcmtk/dcmfg/fgbase.h"
26 #include "dcmtk/dcmiod/iodcommn.h" // for static element helpers
27
FGBase(const DcmFGTypes::E_FGType fgType)28 FGBase::FGBase(const DcmFGTypes::E_FGType fgType)
29 : m_fgType(fgType)
30 {
31 }
32
~FGBase()33 FGBase::~FGBase()
34 {
35 }
36
clearData()37 void FGBase::clearData()
38 {
39 }
40
getType() const41 DcmFGTypes::E_FGType FGBase::getType() const
42 {
43 return m_fgType;
44 }
45
getSharedType() const46 DcmFGTypes::E_FGSharedType FGBase::getSharedType() const
47 {
48 return DcmFGTypes::EFGS_UNKNOWN;
49 }
50
compare(const FGBase & rhs) const51 int FGBase::compare(const FGBase& rhs) const
52 {
53 // Check for equality from FGBase' point of view
54
55 // Same objects?
56 if (this == &rhs)
57 return 0;
58
59 // Type identical?
60 if (this->getType() != rhs.getType())
61 return -1;
62
63 // This is all we can do
64 return 0;
65 }
66
getItemFromFGSequence(DcmItem & source,const DcmTagKey & seqKey,const long unsigned int itemNum,DcmItem * & result)67 OFCondition FGBase::getItemFromFGSequence(DcmItem& source,
68 const DcmTagKey& seqKey,
69 const long unsigned int itemNum,
70 DcmItem*& result)
71 {
72 result = NULL;
73 DcmSequenceOfItems* seq = NULL;
74 if (source.findAndGetSequence(seqKey, seq).bad())
75 {
76 DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey)
77 << ")");
78 return EC_TagNotFound;
79 }
80 result = seq->getItem(itemNum);
81 if (result == NULL)
82 {
83 DCMFG_DEBUG("Functional Group Sequence " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey)
84 << ") does not have " << itemNum - 1 << " items");
85 return FG_EC_NotEnoughItems;
86 }
87 return EC_Normal;
88 }
89
getNumItemsFromFGSequence(DcmItem & source,const DcmTagKey & seqKey,unsigned long & result)90 OFCondition FGBase::getNumItemsFromFGSequence(DcmItem& source, const DcmTagKey& seqKey, unsigned long& result)
91 {
92 result = 0;
93 DcmSequenceOfItems* seq = NULL;
94 if (source.findAndGetSequence(seqKey, seq).bad())
95 {
96 DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey)
97 << ")");
98 return EC_TagNotFound;
99 }
100 result = seq->card();
101 return EC_Normal;
102 }
103
createNewFGSequence(DcmItem & destination,const DcmTagKey & seqKey,const unsigned long numItems,DcmItem * & firstItem)104 OFCondition FGBase::createNewFGSequence(DcmItem& destination,
105 const DcmTagKey& seqKey,
106 const unsigned long numItems,
107 DcmItem*& firstItem)
108 {
109 if (numItems > OFstatic_cast(unsigned long, OFnumeric_limits<signed long>::max()))
110 return EC_IllegalParameter;
111
112 firstItem = NULL;
113 OFCondition result = destination.insertEmptyElement(seqKey, OFTrue /* replace old */);
114 if (result.bad())
115 {
116 DCMFG_ERROR("Could not create Functional Group with sequence " << seqKey << " ("
117 << DcmFGTypes::tagKey2FGType(seqKey) << ")");
118 return FG_EC_CouldNotInsertFG;
119 }
120 DcmItem* dummy = NULL;
121 result = destination.findOrCreateSequenceItem(seqKey, dummy, OFstatic_cast(signed long, numItems));
122 if (result.bad())
123 {
124 // clean up
125 destination.findAndDeleteElement(seqKey);
126 DCMFG_ERROR("Could not create " << numItems << " items in Functional Group with sequence " << seqKey << " ("
127 << DcmFGTypes::tagKey2FGType(seqKey) << ")");
128 return FG_EC_CouldNotInsertFG;
129 }
130 destination.findOrCreateSequenceItem(seqKey, firstItem, 0);
131 return EC_Normal;
132 }
133
134 // ------------------ class FGUnknown ------------------------------------
135
FGUnknown(const DcmTagKey & seqStartTag,const DcmFGTypes::E_FGSharedType sharedType)136 FGUnknown::FGUnknown(const DcmTagKey& seqStartTag, const DcmFGTypes::E_FGSharedType sharedType)
137 : FGBase(DcmFGTypes::EFG_UNKNOWN)
138 , m_seqStartTag(seqStartTag)
139 , m_fgSequence(NULL)
140 , m_sharedType(sharedType)
141 {
142 }
143
FGUnknown(const FGUnknown & rhs)144 FGUnknown::FGUnknown(const FGUnknown& rhs)
145 : FGBase(DcmFGTypes::EFG_UNKNOWN)
146 , m_seqStartTag(rhs.m_seqStartTag)
147 , m_fgSequence(OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone()))
148 , m_sharedType(rhs.m_sharedType)
149 {
150 }
151
operator =(const FGUnknown & rhs)152 FGUnknown& FGUnknown::operator=(const FGUnknown& rhs)
153 {
154 m_seqStartTag = rhs.m_seqStartTag;
155 m_fgSequence = OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone());
156 m_sharedType = rhs.m_sharedType;
157 return *this;
158 }
159
clearData()160 void FGUnknown::clearData()
161 {
162 if (m_fgSequence != NULL)
163 {
164 delete m_fgSequence;
165 m_fgSequence = NULL;
166 }
167 }
168
read(DcmItem & item)169 OFCondition FGUnknown::read(DcmItem& item)
170 {
171 // clear old data
172 clearData();
173 OFCondition result = item.findAndGetSequence(
174 m_seqStartTag, m_fgSequence, OFFalse /* no depth search */, OFTrue /* create copy! */);
175 if (result.bad())
176 {
177 if (m_fgSequence != NULL)
178 delete m_fgSequence;
179 m_fgSequence = NULL;
180 }
181 return result;
182 }
183
write(DcmItem & item)184 OFCondition FGUnknown::write(DcmItem& item)
185 {
186 return item.insert(new DcmSequenceOfItems(*m_fgSequence), OFTrue /* replace old! */);
187 }
188
check() const189 OFCondition FGUnknown::check() const
190 {
191 return EC_Normal;
192 }
193
compare(const FGBase & rhs) const194 int FGUnknown::compare(const FGBase& rhs) const
195 {
196 int result = FGBase::compare(rhs);
197 if (result == 0)
198 {
199 const FGUnknown* myRhs = OFstatic_cast(const FGUnknown*, &rhs);
200
201 // Compare all elements
202 if (m_seqStartTag == myRhs->m_seqStartTag)
203 {
204 if (m_fgSequence && myRhs->m_fgSequence)
205 {
206 result = m_fgSequence->compare(*(myRhs->m_fgSequence));
207 }
208 else if (!m_fgSequence && !myRhs->m_fgSequence) // if both are not set, objects are still equal
209 {
210 result = 0;
211 }
212 else if (m_fgSequence)
213 {
214 result = 1; // this object is bigger (more information)
215 }
216 else if (myRhs->m_fgSequence)
217 {
218 result = -1; // rhs object is bigger (more information)
219 }
220 }
221 else
222 {
223 result = (m_seqStartTag < myRhs->m_seqStartTag) ? -1 : 1;
224 }
225 }
226
227 return result;
228 }
229
~FGUnknown()230 FGUnknown::~FGUnknown()
231 {
232 clearData();
233 }
234
clone() const235 FGBase* FGUnknown::clone() const
236 {
237 FGUnknown* copy = new FGUnknown(this->m_seqStartTag);
238 if (copy)
239 {
240 *(copy->m_fgSequence) = *(this->m_fgSequence);
241 }
242 return copy;
243 }
244