1 /*
2 *
3 * Copyright (C) 2000-2019, OFFIS e.V.
4 * All rights reserved. See COPYRIGHT file for details.
5 *
6 * This software and supporting documentation were developed by
7 *
8 * OFFIS e.V.
9 * R&D Division Health
10 * Escherweg 2
11 * D-26121 Oldenburg, Germany
12 *
13 *
14 * Module: dcmsr
15 *
16 * Author: Joerg Riesmeier
17 *
18 * Purpose:
19 * classes: DSRDateTimeTreeNode
20 *
21 */
22
23
24 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
25
26 #include "dcmtk/dcmsr/dsrtypes.h"
27 #include "dcmtk/dcmsr/dsrdtitn.h"
28 #include "dcmtk/dcmsr/dsrxmld.h"
29
30 #include "dcmtk/dcmdata/dcdeftag.h"
31 #include "dcmtk/dcmdata/dcvrdt.h"
32
33
DSRDateTimeTreeNode(const E_RelationshipType relationshipType)34 DSRDateTimeTreeNode::DSRDateTimeTreeNode(const E_RelationshipType relationshipType)
35 : DSRDocumentTreeNode(relationshipType, VT_DateTime),
36 DSRStringValue()
37 {
38 }
39
40
DSRDateTimeTreeNode(const E_RelationshipType relationshipType,const OFString & dateTimeValue,const OFBool check)41 DSRDateTimeTreeNode::DSRDateTimeTreeNode(const E_RelationshipType relationshipType,
42 const OFString &dateTimeValue,
43 const OFBool check)
44 : DSRDocumentTreeNode(relationshipType, VT_DateTime),
45 DSRStringValue(dateTimeValue, check)
46 {
47 }
48
49
DSRDateTimeTreeNode(const DSRDateTimeTreeNode & node)50 DSRDateTimeTreeNode::DSRDateTimeTreeNode(const DSRDateTimeTreeNode &node)
51 : DSRDocumentTreeNode(node),
52 DSRStringValue(node)
53 {
54 }
55
56
~DSRDateTimeTreeNode()57 DSRDateTimeTreeNode::~DSRDateTimeTreeNode()
58 {
59 }
60
61
operator ==(const DSRDocumentTreeNode & node) const62 OFBool DSRDateTimeTreeNode::operator==(const DSRDocumentTreeNode &node) const
63 {
64 /* call comparison operator of base class (includes check of value type) */
65 OFBool result = DSRDocumentTreeNode::operator==(node);
66 if (result)
67 {
68 /* it's safe to cast the type since the value type has already been checked */
69 result = DSRStringValue::operator==(OFstatic_cast(const DSRDateTimeTreeNode &, node).getValue());
70 }
71 return result;
72 }
73
74
operator !=(const DSRDocumentTreeNode & node) const75 OFBool DSRDateTimeTreeNode::operator!=(const DSRDocumentTreeNode &node) const
76 {
77 /* call comparison operator of base class (includes check of value type) */
78 OFBool result = DSRDocumentTreeNode::operator!=(node);
79 if (!result)
80 {
81 /* it's safe to cast the type since the value type has already been checked */
82 result = DSRStringValue::operator!=(OFstatic_cast(const DSRDateTimeTreeNode &, node).getValue());
83 }
84 return result;
85 }
86
87
clone() const88 DSRDateTimeTreeNode *DSRDateTimeTreeNode::clone() const
89 {
90 return new DSRDateTimeTreeNode(*this);
91 }
92
93
clear()94 void DSRDateTimeTreeNode::clear()
95 {
96 DSRDocumentTreeNode::clear();
97 DSRStringValue::clear();
98 }
99
100
isValid() const101 OFBool DSRDateTimeTreeNode::isValid() const
102 {
103 /* ConceptNameCodeSequence required */
104 return DSRDocumentTreeNode::isValid() && getConceptName().isValid() && hasValidValue();
105 }
106
107
hasValidValue() const108 OFBool DSRDateTimeTreeNode::hasValidValue() const
109 {
110 return checkCurrentValue().good();
111 }
112
113
print(STD_NAMESPACE ostream & stream,const size_t flags) const114 OFCondition DSRDateTimeTreeNode::print(STD_NAMESPACE ostream &stream,
115 const size_t flags) const
116 {
117 OFCondition result = DSRDocumentTreeNode::print(stream, flags);
118 if (result.good())
119 {
120 DCMSR_PRINT_ANSI_ESCAPE_CODE(DCMSR_ANSI_ESCAPE_CODE_DELIMITER)
121 stream << "=";
122 DCMSR_PRINT_ANSI_ESCAPE_CODE(DCMSR_ANSI_ESCAPE_CODE_ITEM_VALUE)
123 DSRStringValue::print(stream);
124 }
125 return result;
126 }
127
128
writeXML(STD_NAMESPACE ostream & stream,const size_t flags) const129 OFCondition DSRDateTimeTreeNode::writeXML(STD_NAMESPACE ostream &stream,
130 const size_t flags) const
131 {
132 OFString tmpString;
133 OFCondition result = EC_Normal;
134 writeXMLItemStart(stream, flags);
135 result = DSRDocumentTreeNode::writeXML(stream, flags);
136 /* output time in ISO 8601 format */
137 DcmDateTime::getISOFormattedDateTimeFromString(getValue(), tmpString, OFTrue /*seconds*/, OFFalse /*fraction*/,
138 OFTrue /*timeZone*/, OFFalse /*createMissingPart*/, "T" /*dateTimeSeparator*/, "" /*timeZoneSeparator*/);
139 writeStringValueToXML(stream, tmpString, "value", (flags & XF_writeEmptyTags) > 0);
140 writeXMLItemEnd(stream, flags);
141 return result;
142 }
143
144
readContentItem(DcmItem & dataset,const size_t flags)145 OFCondition DSRDateTimeTreeNode::readContentItem(DcmItem &dataset,
146 const size_t flags)
147 {
148 /* read DateTime */
149 return DSRStringValue::read(dataset, DCM_DateTime, flags);
150 }
151
152
writeContentItem(DcmItem & dataset) const153 OFCondition DSRDateTimeTreeNode::writeContentItem(DcmItem &dataset) const
154 {
155 /* write DateTime */
156 return DSRStringValue::write(dataset, DCM_DateTime);
157 }
158
159
readXMLContentItem(const DSRXMLDocument & doc,DSRXMLCursor cursor,const size_t)160 OFCondition DSRDateTimeTreeNode::readXMLContentItem(const DSRXMLDocument &doc,
161 DSRXMLCursor cursor,
162 const size_t /*flags*/)
163 {
164 OFString tmpString;
165 /* retrieve value from XML element "value" */
166 OFCondition result = setValue(getValueFromXMLNodeContent(doc, doc.getNamedChildNode(cursor, "value"), tmpString));
167 if (result == EC_IllegalParameter)
168 result = SR_EC_InvalidValue;
169 return result;
170 }
171
172
getValueFromXMLNodeContent(const DSRXMLDocument & doc,DSRXMLCursor cursor,OFString & dateTimeValue,const OFBool clearString)173 OFString &DSRDateTimeTreeNode::getValueFromXMLNodeContent(const DSRXMLDocument &doc,
174 DSRXMLCursor cursor,
175 OFString &dateTimeValue,
176 const OFBool clearString)
177 {
178 if (clearString)
179 dateTimeValue.clear();
180 /* check whether node is valid */
181 if (cursor.valid())
182 {
183 OFString tmpString;
184 /* retrieve value from XML element */
185 if (!doc.getStringFromNodeContent(cursor, tmpString).empty())
186 {
187 OFDateTime tmpDateTime;
188 /* convert ISO to DICOM format */
189 if (tmpDateTime.setISOFormattedDateTime(tmpString))
190 {
191 /* example of XML date/time format with time zone: 2010-12-31T15:30:00+01:00 */
192 const OFBool hasTimeZone = (tmpString.length() >= 25);
193 DcmDateTime::getDicomDateTimeFromOFDateTime(tmpDateTime, dateTimeValue,
194 OFTrue /*seconds*/, OFFalse /*fraction*/, hasTimeZone /*timeZone*/);
195 }
196 }
197 }
198 return dateTimeValue;
199 }
200
201
renderHTMLContentItem(STD_NAMESPACE ostream & docStream,STD_NAMESPACE ostream &,const size_t,size_t &,const size_t flags) const202 OFCondition DSRDateTimeTreeNode::renderHTMLContentItem(STD_NAMESPACE ostream &docStream,
203 STD_NAMESPACE ostream & /*annexStream*/,
204 const size_t /*nestingLevel*/,
205 size_t & /*annexNumber*/,
206 const size_t flags) const
207 {
208 /* render ConceptName */
209 OFCondition result = renderHTMLConceptName(docStream, flags);
210 /* render DateTime */
211 if (result.good())
212 {
213 OFString htmlString;
214 if (!(flags & DSRTypes::HF_renderItemsSeparately))
215 {
216 if (flags & DSRTypes::HF_XHTML11Compatibility)
217 docStream << "<span class=\"datetime\">";
218 else if (flags & DSRTypes::HF_HTML32Compatibility)
219 docStream << "<u>";
220 else /* HTML 4.01 */
221 docStream << "<span class=\"under\">";
222 }
223 docStream << dicomToReadableDateTime(getValue(), htmlString);
224 if (!(flags & DSRTypes::HF_renderItemsSeparately))
225 {
226 if (flags & DSRTypes::HF_HTML32Compatibility)
227 docStream << "</u>";
228 else
229 docStream << "</span>";
230 }
231 docStream << OFendl;
232 }
233 return result;
234 }
235
236
checkValue(const OFString & dateTimeValue) const237 OFCondition DSRDateTimeTreeNode::checkValue(const OFString &dateTimeValue) const
238 {
239 /* first, make sure that the mandatory value is non-empty */
240 OFCondition result = DSRStringValue::checkValue(dateTimeValue);
241 /* then, check whether the passed value is valid */
242 if (result.good())
243 result = DcmDateTime::checkStringValue(dateTimeValue, "1");
244 return result;
245 }
246