1 /*
2  *
3  *  Copyright (C) 2000-2020, 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: DSRTypes
20  *
21  */
22 
23 
24 #ifndef DSRTYPES_H
25 #define DSRTYPES_H
26 
27 #include "dcmtk/config/osconfig.h"   /* make sure OS specific configuration is included first */
28 
29 #include "dcmtk/dcmsr/dsdefine.h"
30 
31 #include "dcmtk/dcmdata/dcelem.h"
32 #include "dcmtk/dcmdata/dcitem.h"
33 #include "dcmtk/dcmdata/dcsequen.h"
34 
35 #include "dcmtk/ofstd/ofstream.h"
36 #include "dcmtk/ofstd/ofstring.h"
37 #include "dcmtk/ofstd/oftypes.h"
38 #include "dcmtk/ofstd/ofcond.h"
39 #include "dcmtk/oflog/oflog.h"
40 
41 
42 // global definitions for logging mechanism provided by the oflog module
43 
44 extern DCMTK_DCMSR_EXPORT OFLogger DCM_dcmsrLogger;
45 
46 #define DCMSR_TRACE(msg) OFLOG_TRACE(DCM_dcmsrLogger, msg)
47 #define DCMSR_DEBUG(msg) OFLOG_DEBUG(DCM_dcmsrLogger, msg)
48 #define DCMSR_INFO(msg)  OFLOG_INFO(DCM_dcmsrLogger, msg)
49 #define DCMSR_WARN(msg)  OFLOG_WARN(DCM_dcmsrLogger, msg)
50 #define DCMSR_ERROR(msg) OFLOG_ERROR(DCM_dcmsrLogger, msg)
51 #define DCMSR_FATAL(msg) OFLOG_FATAL(DCM_dcmsrLogger, msg)
52 
53 
54 // include this file in doxygen documentation
55 
56 /** @file dsrtypes.h
57  *  @brief type definitions, constants and helper functions for the dcmsr module
58  */
59 
60 
61 /*---------------------*
62  *  macro definitions  *
63  *---------------------*/
64 
65 // private coding scheme designator used for internal codes
66 #define OFFIS_CODING_SCHEME_DESIGNATOR "99_OFFIS_DCMTK"
67 // name of the private coding scheme
68 #define OFFIS_CODING_SCHEME_NAME "OFFIS DCMTK Coding Scheme"
69 // organization responsible for the private coding scheme
70 #define OFFIS_CODING_SCHEME_RESPONSIBLE_ORGANIZATION "OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany"
71 
72 // protocol, hostname and CGI script name used for HTML hyperlinks to composite objects
73 #define HTML_HYPERLINK_PREFIX_FOR_CGI "http://localhost/dicom.cgi"
74 // URL of the DICOM toolkit DCMTK
75 #define DCMTK_INTERNET_URL "http://dicom.offis.de/dcmtk"
76 
77 // XML namespace URI for dcmsr module
78 #define DCMSR_XML_NAMESPACE_URI "http://dicom.offis.de/dcmsr"
79 // XML Schema file for dcmsr module
80 #define DCMSR_XML_XSD_FILE "dsr2xml.xsd"
81 // XML Schema Instance URI
82 #define XML_SCHEMA_INSTANCE_URI "http://www.w3.org/2001/XMLSchema-instance"
83 
84 // ANSI escape codes for color output of the print() method
85 #define DCMSR_ANSI_ESCAPE_CODE_RESET             "\033[0m"
86 #define DCMSR_ANSI_ESCAPE_CODE_DOCUMENT_TYPE     "\033[22m\033[35m"
87 #define DCMSR_ANSI_ESCAPE_CODE_HEADER_NAME       "\033[1m\033[34m"
88 #define DCMSR_ANSI_ESCAPE_CODE_HEADER_VALUE      "\033[1m\033[37m"
89 #define DCMSR_ANSI_ESCAPE_CODE_ITEM_POSITION     "\033[22m\033[36m"
90 #define DCMSR_ANSI_ESCAPE_CODE_VALUE_TYPE        "\033[22m\033[31m"
91 #define DCMSR_ANSI_ESCAPE_CODE_RELATIONSHIP_TYPE "\033[22m\033[32m"
92 #define DCMSR_ANSI_ESCAPE_CODE_CONCEPT_NAME      "\033[22m\033[33m"
93 #define DCMSR_ANSI_ESCAPE_CODE_ITEM_VALUE        "\033[1m\033[37m"
94 #define DCMSR_ANSI_ESCAPE_CODE_TEMPLATE_ID       "\033[22m\033[35m"
95 #define DCMSR_ANSI_ESCAPE_CODE_ANNOTATION        "\033[22m\033[36m"
96 #define DCMSR_ANSI_ESCAPE_CODE_DELIMITER         "\033[1m\033[30m"
97 
98 // helper macro for the conditional usage of ANSI escape codes
99 #define DCMSR_PRINT_ANSI_ESCAPE_CODE(ansi_code)  \
100     if (flags & PF_useANSIEscapeCodes)           \
101     {                                            \
102         stream << ansi_code;                     \
103     }
104 
105 
106 /*------------------------*
107  *  forward declarations  *
108  *------------------------*/
109 
110 class DSRXMLCursor;
111 class DSRXMLDocument;
112 class DSRDocumentTreeNode;
113 class DSRIODConstraintChecker;
114 
115 
116 /*-----------------------*
117  *  constant definitions  *
118  *-----------------------*/
119 
120 /** @name specific error conditions for module dcmsr.
121  *  These error codes can be used in addition to the general purpose
122  *  codes defined in module dcmdata.
123  */
124 //@{
125 
126 /// error: the document type (SOP class UID) is unknown or not supported
127 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_UnknownDocumentType;
128 
129 /// error: the document status is invalid
130 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidDocument;
131 
132 /// error: the document tree is invalid (e.g. corrupted structure)
133 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidDocumentTree;
134 
135 /// error: a mandatory attribute is missing
136 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_MandatoryAttributeMissing;
137 
138 /// error: a value is invalid according to the DICOM standard
139 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidValue;
140 
141 /// error: a value is not supported by this implementation
142 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_UnsupportedValue;
143 
144 /// error: an unknown value type is used
145 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_UnknownValueType;
146 
147 /// error: an unknown relationship type is used
148 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_UnknownRelationshipType;
149 
150 /// error: the by-value relationship between two content items is not allowed
151 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidByValueRelationship;
152 
153 /// error: the by-reference relationship between two content items is not allowed
154 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidByReferenceRelationship;
155 
156 /// error: the specified SOP instance could not be found
157 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_SOPInstanceNotFound;
158 
159 /// error: a SOP instance has different SOP classes
160 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_DifferentSOPClassesForAnInstance;
161 
162 /// error: the specified coding scheme designator could not be found
163 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CodingSchemeNotFound;
164 
165 /// error: the XML structure is corrupted (XML parser error)
166 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CorruptedXMLStructure;
167 
168 /// error: the requested representation is not available
169 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_RepresentationNotAvailable;
170 
171 /// error: an icon image could not be created from the given DICOM image
172 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotCreateIconImage;
173 
174 /// error: a new content item could not be added to the current one
175 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotAddContentItem;
176 
177 /// error: an invalid concept name code has been passed or is used
178 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidConceptName;
179 
180 /// error: a given subtree could not be inserted at the current node
181 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotInsertSubTree;
182 
183 /// error: the current relationship type cannot be replaced by the given one
184 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotChangeRelationshipType;
185 
186 /// error: the document tree does not comply with the given SR IOD constraints
187 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_IncompatibleDocumentTree;
188 
189 /// error: the specified content item (node) could not be found
190 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_ContentItemNotFound;
191 
192 /// error: the specified subtree could not be removed from the document tree
193 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotRemoveSubTree;
194 
195 /// error: the document tree is empty (and this is not allowed in this context)
196 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_EmptyDocumentTree;
197 
198 /// error: the content item is invalid, e.g. the concept name or the stored value
199 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidContentItem;
200 
201 /// error: template identification cannot be used, i.e. requirements are not fulfilled
202 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotUseTemplateIdentification;
203 
204 /// error: cannot add content item or insert subtree to non-extensible template
205 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_NonExtensibleTemplate;
206 
207 /// error: cannot add coded entry to non-extensible context group
208 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_NonExtensibleContextGroup;
209 
210 /// error: a given coded entry in not contained in the context group
211 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CodedEntryNotInContextGroup;
212 
213 /// normal: a given coded entry is contained in the context group (i.e. a standard code)
214 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CodedEntryInStandardContextGroup;
215 
216 /// normal: a given coded entry is known as an extension of the context group
217 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CodedEntryIsExtensionOfContextGroup;
218 
219 /// error: a value violates the value set constraint of a particular template row
220 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_ValueSetConstraintViolated;
221 
222 /// error: the internally managed structure of a template class is invalid
223 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_InvalidTemplateStructure;
224 
225 /// error: cannot process document tree with included templates
226 extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotProcessIncludedTemplates;
227 
228 //@}
229 
230 
231 /*---------------------*
232  *  class declaration  *
233  *---------------------*/
234 
235 /** General purpose class hiding global functions, constants and types from the
236  *  global namespace.  Some of them might be moved to 'ofstd' later on.
237  *  All functions and constants are static and can, therefore, be accessed without
238  *  creating an instance of this class.
239  */
240 class DCMTK_DCMSR_EXPORT DSRTypes
241 {
242 
243   public:
244 
245   // --- constant declarations ---
246 
247     /** @name read() flags
248      *  These flags can be combined and passed to the read() methods.
249      *  The 'shortcut' flags can be used for common combinations.
250      */
251     //@{
252 
253     /// read digital signatures from dataset
254     static const size_t RF_readDigitalSignatures;
255 
256     /// accept unknown/missing relationship type
257     static const size_t RF_acceptUnknownRelationshipType;
258 
259     /// accept invalid content item value (e.g. violation of VR or VM definition)
260     static const size_t RF_acceptInvalidContentItemValue;
261 
262     /// ignore relationship constraints for this document class
263     static const size_t RF_ignoreRelationshipConstraints;
264 
265     /// do not abort on content item errors (e.g. missing value type specific attributes)
266     static const size_t RF_ignoreContentItemErrors;
267 
268     /// do not abort when detecting an invalid content item, skip invalid sub-tree instead
269     static const size_t RF_skipInvalidContentItems;
270 
271     /// show the currently processed content item (e.g. "1.2.3")
272     static const size_t RF_showCurrentlyProcessedItem;
273     //@}
274 
275 
276     /** @name renderHTML() flags
277      *  These flags can be combined and passed to the renderHMTL() methods.
278      *  Please note that only the 'external' flags can be used from outside
279      *  this library.  The 'shortcut' flags can be used for common combinations.
280      */
281     //@{
282 
283     /// external: never expand child nodes inline
284     static const size_t HF_neverExpandChildrenInline;
285 
286     /// external: always expand child nodes inline
287     static const size_t HF_alwaysExpandChildrenInline;
288 
289     /// external: render codes even if they appear inline
290     static const size_t HF_renderInlineCodes;
291 
292     /// external: render code details as a tooltip (not with HTML 3.2)
293     static const size_t HF_useCodeDetailsTooltip;
294 
295     /// external: render concept name codes (default: code meaning only)
296     static const size_t HF_renderConceptNameCodes;
297 
298     /// external: render the code of the numeric measurement unit
299     static const size_t HF_renderNumericUnitCodes;
300 
301     /// external: use code meaning for the numeric measurement unit (default: code value)
302     static const size_t HF_useCodeMeaningAsUnit;
303 
304     /// external: use patient information as document title (default: document type)
305     static const size_t HF_renderPatientTitle;
306 
307     /// external: render no general document information (header)
308     static const size_t HF_renderNoDocumentHeader;
309 
310     /// external: render dcmtk/dcmsr comment at the end of the document
311     static const size_t HF_renderDcmtkFootnote;
312 
313     /// external: render the full data of all content items
314     static const size_t HF_renderFullData;
315 
316     /// external: render section titles inline (default: separate paragraph)
317     static const size_t HF_renderSectionTitlesInline;
318 
319     /// external: copy Cascading Style Sheet (CSS) content to HTML file
320     static const size_t HF_copyStyleSheetContent;
321 
322     /// external: output compatible to HTML version 3.2 (default: 4.01)
323     static const size_t HF_HTML32Compatibility;
324 
325     /// external: output compatible to XHTML version 1.1 (default: HTML 4.01)
326     static const size_t HF_XHTML11Compatibility;
327 
328     /// external: add explicit reference to HTML document type (DTD)
329     static const size_t HF_addDocumentTypeReference;
330 
331     /// external: omit generator meta element referring to the DCMTK
332     static const size_t HF_omitGeneratorMetaElement;
333 
334     /// internal: render items separately (for container with SEPARATE flag)
335     static const size_t HF_renderItemsSeparately;
336 
337     /// internal: expand items inline when they are short and have no child nodes
338     static const size_t HF_renderItemInline;
339 
340     /// internal: content item is rendered fully inside the annex
341     static const size_t HF_currentlyInsideAnnex;
342 
343     /// internal: create footnote references
344     static const size_t HF_createFootnoteReferences;
345 
346     /// internal: convert non-ASCII characters (> #127) to &\#nnn;
347     static const size_t HF_convertNonASCIICharacters;
348 
349     /// shortcut: render all codes
350     static const size_t HF_renderAllCodes;
351 
352     /// shortcut: filter all flags that are only used internally
353     static const size_t HF_internalUseOnly;
354     //@}
355 
356 
357     /** @name read/writeXML() flags
358      *  These flags can be combined and passed to the read/writeXML() methods.
359      *  The 'shortcut' flags can be used for common combinations.
360      */
361     //@{
362 
363     /// write: write all tags even if their value is empty
364     static const size_t XF_writeEmptyTags;
365 
366     /// write: write template identification information (TID and mapping resource)
367     static const size_t XF_writeTemplateIdentification;
368 
369     /// write: always write item identifier "id", not only when item is referenced
370     static const size_t XF_alwaysWriteItemIdentifier;
371 
372     /// write: encode code value, coding scheme designator and coding scheme version as attribute instead of element text
373     static const size_t XF_codeComponentsAsAttribute;
374 
375     /// write: encode relationship type as attribute instead of element text
376     static const size_t XF_relationshipTypeAsAttribute;
377 
378     /// write: encode value type as attribute instead of element text
379     static const size_t XF_valueTypeAsAttribute;
380 
381     /// write: encode template identifier as attribute instead of element text
382     static const size_t XF_templateIdentifierAsAttribute;
383 
384     /// write: add DCMSR namespace declaration to the XML output
385     static const size_t XF_useDcmsrNamespace;
386 
387     /// write: add Schema reference to XML document
388     static const size_t XF_addSchemaReference;
389 
390     /// read: validate content of XML document against Schema
391     static const size_t XF_validateSchema;
392 
393     /// read/write: template identification element encloses content items
394     static const size_t XF_templateElementEnclosesItems;
395 
396     /// write: add comments with details at beginning/end of included template (might be useful for debugging purposes)
397     static const size_t XF_addCommentsForIncludedTemplate;
398 
399     /// read: accept empty Study/Series/SOP Instance UID attribute values (must be filled later)
400     static const size_t XF_acceptEmptyStudySeriesInstanceUID;
401 
402     /// shortcut: combines all XF_xxxAsAttribute write flags (see above)
403     static const size_t XF_encodeEverythingAsAttribute;
404     //@}
405 
406 
407     /** @name print() flags
408      *  These flags can be combined and passed to the print() methods.
409      *  The 'shortcut' flags can be used for common combinations.
410      */
411     //@{
412 
413     /// print item position ("1.2.3") instead of line indentation
414     static const size_t PF_printItemPosition;
415 
416     /// shorten long item value (e.g. long texts)
417     static const size_t PF_shortenLongItemValues;
418 
419     /// print SOP instance UID of referenced objects
420     static const size_t PF_printSOPInstanceUID;
421 
422     /// print coding scheme designator/version and code value of concept names
423     static const size_t PF_printConceptNameCodes;
424 
425     /// print no general document information (header)
426     static const size_t PF_printNoDocumentHeader;
427 
428     /// print template identification (TID and mapping resource)
429     static const size_t PF_printTemplateIdentification;
430 
431     /// use ANSI escape codes for output
432     static const size_t PF_useANSIEscapeCodes;
433 
434     /// print long SOP class name of referenced objects (default: short name for images)
435     static const size_t PF_printLongSOPClassName;
436 
437     /// print SOP class UID of referenced objects (instead of the name)
438     static const size_t PF_printSOPClassUID;
439 
440     /// print code triple for invalid codes (instead of the text "invalid code")
441     static const size_t PF_printInvalidCodes;
442 
443     /// print node ID at the beginning of each line (might be useful for debugging purposes)
444     static const size_t PF_printNodeID;
445 
446     /// indicate with a "*" that the "enhanced encoding mode" is used for codes
447     static const size_t PF_indicateEnhancedEncodingMode;
448 
449     /// print annotation of a content item (optional, e.g. user-defined information)
450     static const size_t PF_printAnnotation;
451 
452     /// do not print internal "included template" nodes (position counter is still increased)
453     static const size_t PF_hideIncludedTemplateNodes;
454 
455     /// do not count internal "included template" nodes (only with PF_hideIncludedTemplateNodes)
456     static const size_t PF_dontCountIncludedTemplateNodes;
457 
458     /// print text "empty code" for empty codes (instead of "invalid code")
459     static const size_t PF_printEmptyCodes;
460 
461     /// shortcut: print all codes (combines all PF_printXxxCodes flags, see above)
462     static const size_t PF_printAllCodes;
463     //@}
464 
465 
466     /** @name checkByReferenceRelationships() modes
467      *  These modes can be combined and passed to the checkByReferenceRelationships() method.
468      */
469     //@{
470 
471     /// update the position string using the node ID
472     static const size_t CM_updatePositionString;
473 
474     /// update the node ID using the position string
475     static const size_t CM_updateNodeID;
476 
477     /// reset the reference target flag for all nodes
478     static const size_t CM_resetReferenceTargetFlag;
479     //@}
480 
481 
482     /** @name checkByReferenceRelationships() bit masks
483      *  These bit masks are used to "filter" valid flags passed to checkByReferenceRelationships().
484      */
485     //@{
486 
487     /// bit mask (filter) for valid print flags (see PF_xxx)
488     static const size_t CB_maskPrintFlags;
489 
490     /// bit mask (filter) for valid read flags (see RF_xxx)
491     static const size_t CB_maskReadFlags;
492 
493     //@}
494 
495 
496   // --- type definitions ---
497 
498     /** SR document types (DICOM IOD)
499      */
500     enum E_DocumentType
501     {
502         /// internal type used to indicate an error
503         DT_invalid,
504         /// internal type used to indicate an unknown/unsupported document type
505         DT_unknown = DT_invalid,
506         /// DICOM IOD: Basic Text SR
507         DT_BasicTextSR,
508         /// DICOM IOD: Enhanced SR
509         DT_EnhancedSR,
510         /// DICOM IOD: Comprehensive SR
511         DT_ComprehensiveSR,
512         /// DICOM IOD: Key Object Selection Document
513         DT_KeyObjectSelectionDocument,
514         /// DICOM IOD: Mammography CAD SR
515         DT_MammographyCadSR,
516         /// DICOM IOD: Chest CAD SR
517         DT_ChestCadSR,
518         /// DICOM IOD: Colon CAD SR
519         DT_ColonCadSR,
520         /// DICOM IOD: Procedure Log
521         DT_ProcedureLog,
522         /// DICOM IOD: X-Ray Radiation Dose SR
523         DT_XRayRadiationDoseSR,
524         /// DICOM IOD: Spectacle Prescription Report
525         DT_SpectaclePrescriptionReport,
526         /// DICOM IOD: Macular Grid Thickness and Volume Report
527         DT_MacularGridThicknessAndVolumeReport,
528         /// DICOM IOD: Implantation Plan SR Document
529         DT_ImplantationPlanSRDocument,
530         /// DICOM IOD: Comprehensive 3D SR
531         DT_Comprehensive3DSR,
532         /// DICOM IOD: Radiopharmaceutical Radiation Dose SR
533         DT_RadiopharmaceuticalRadiationDoseSR,
534         /// DICOM IOD: Extensible SR (not yet implemented)
535         DT_ExtensibleSR,
536         /// DICOM IOD: Acquisition Context SR
537         DT_AcquisitionContextSR,
538         /// DICOM IOD: Simplified Adult Echo SR
539         DT_SimplifiedAdultEchoSR,
540         /// DICOM IOD: Patient Radiation Dose SR
541         DT_PatientRadiationDoseSR,
542         /// DICOM IOD: Performed Imaging Agent Administration SR
543         DT_PerformedImagingAgentAdministrationSR,
544         /// DICOM IOD: Planned Imaging Agent Administration SR
545         DT_PlannedImagingAgentAdministrationSR,
546         /// DICOM IOD: Rendition Selection Document
547         DT_RenditionSelectionDocument,
548         /// internal type used to mark the last entry
549         DT_last = DT_RenditionSelectionDocument
550     };
551 
552     /** SR relationship types
553      */
554     enum E_RelationshipType
555     {
556         /// internal type used to indicate an error
557         RT_invalid,
558         /// internal type used to indicate an unknown relationship type (defined term)
559         RT_unknown,
560         /// internal type used for the document root
561         RT_isRoot,
562         /// DICOM Relationship Type: CONTAINS
563         RT_contains,
564         /// DICOM Relationship Type: HAS OBS CONTEXT
565         RT_hasObsContext,
566         /// DICOM Relationship Type: HAS ACQ CONTEXT
567         RT_hasAcqContext,
568         /// DICOM Relationship Type: HAS CONCEPT MOD
569         RT_hasConceptMod,
570         /// DICOM Relationship Type: HAS PROPERTIES
571         RT_hasProperties,
572         /// DICOM Relationship Type: INFERRED FROM
573         RT_inferredFrom,
574         /// DICOM Relationship Type: SELECTED FROM
575         RT_selectedFrom,
576         /// internal type used to mark the last entry
577         RT_last = RT_selectedFrom
578     };
579 
580     /** SR value types
581      */
582     enum E_ValueType
583     {
584         /// internal type used to indicate an error
585         VT_invalid,
586         /// DICOM Value Type: TEXT
587         VT_Text,
588         /// DICOM Value Type: CODE
589         VT_Code,
590         /// DICOM Value Type: NUM
591         VT_Num,
592         /// DICOM Value Type: DATETIME
593         VT_DateTime,
594         /// DICOM Value Type: DATE
595         VT_Date,
596         /// DICOM Value Type: TIME
597         VT_Time,
598         /// DICOM Value Type: UIDREF
599         VT_UIDRef,
600         /// DICOM Value Type: PNAME
601         VT_PName,
602         /// DICOM Value Type: SCOORD
603         VT_SCoord,
604         /// DICOM Value Type: SCOORD3D
605         VT_SCoord3D,
606         /// DICOM Value Type: TCOORD
607         VT_TCoord,
608         /// DICOM Value Type: COMPOSITE
609         VT_Composite,
610         /// DICOM Value Type: IMAGE
611         VT_Image,
612         /// DICOM Value Type: WAVEFORM
613         VT_Waveform,
614         /// DICOM Value Type: CONTAINER
615         VT_Container,
616         /// internal type used to indicate by-reference relationships
617         VT_byReference,
618         /// internal type used to indicate (enclose) included templates
619         VT_includedTemplate,
620         /// internal type used to mark the last entry
621         VT_last = VT_includedTemplate
622     };
623 
624     /** Softcopy presentation state types.  Used for content item IMAGE.
625      */
626     enum E_PresentationStateType
627     {
628         /// internal type used to indicate an error
629         PT_invalid,
630         /// internal type used to indicate an unknown presentation state type (SOP class)
631         PT_unknown = PT_invalid,
632         /// Grayscale Softcopy Presentation State (GSPS)
633         PT_Grayscale,
634         /// Color Softcopy Presentation State (CSPS)
635         PT_Color,
636         /// Pseudo-Color Softcopy Presentation State (PCSPS)
637         PT_PseudoColor,
638         /// Blending Softcopy Presentation State (BSPS)
639         PT_Blending,
640         /// XA/XRF Grayscale Softcopy Presentation State (XGSPS)
641         PT_XAXRFGrayscale,
642         /// Grayscale Planar MPR Volumetric Presentation State (GP-VPS)
643         PT_GrayscalePlanarMPR,
644         /// Compositing Planar MPR Volumetric Presentation State (CP-VPS)
645         PT_CompositingPlanarMPR,
646         /// Advanced Blending Presentation State (ABPS)
647         PT_AdvancedBlending,
648         /// Volume Rendering Volumetric Presentation State (VR-VPS)
649         PT_VolumeRendering,
650         /// Segmented Volume Rendering Volumetric Presentation State (SVR-VPS)
651         PT_SegmentedVolumeRendering,
652         /// Multiple Volume Rendering Volumetric Presentation State (MVR-VPS)
653         PT_MultipleVolumeRendering,
654         /// internal type used to mark the last entry
655         PT_last = PT_MultipleVolumeRendering
656     };
657 
658     /** SR graphic types.  Used for content item SCOORD.
659      */
660     enum E_GraphicType
661     {
662         /// internal type used to indicate an error
663         GT_invalid,
664         /// internal type used to indicate an unknown graphic type (defined term)
665         GT_unknown = GT_invalid,
666         /// DICOM Graphic Type: POINT
667         GT_Point,
668         /// DICOM Graphic Type: MULTIPOINT
669         GT_Multipoint,
670         /// DICOM Graphic Type: POLYLINE
671         GT_Polyline,
672         /// DICOM Graphic Type: CIRCLE
673         GT_Circle,
674         /// DICOM Graphic Type: ELLIPSE
675         GT_Ellipse,
676         /// internal type used to mark the last entry
677         GT_last = GT_Ellipse
678     };
679 
680     /** SR graphic types (3D).  Used for content item SCOORD3D.
681      */
682     enum E_GraphicType3D
683     {
684         /// internal type used to indicate an error
685         GT3_invalid,
686         /// internal type used to indicate an unknown graphic type (defined term)
687         GT3_unknown = GT3_invalid,
688         /// DICOM Graphic Type: POINT
689         GT3_Point,
690         /// DICOM Graphic Type: MULTIPOINT
691         GT3_Multipoint,
692         /// DICOM Graphic Type: POLYLINE
693         GT3_Polyline,
694         /// DICOM Graphic Type: POLYGON
695         GT3_Polygon,
696         /// DICOM Graphic Type: ELLIPSE
697         GT3_Ellipse,
698         /// DICOM Graphic Type: ELLIPSOID
699         GT3_Ellipsoid,
700         /// internal type used to mark the last entry
701         GT3_last = GT3_Ellipsoid
702     };
703 
704     /** SR temporal range types.  Used for content item TCOORD.
705      */
706     enum E_TemporalRangeType
707     {
708         /// internal type used to indicate an error
709         TRT_invalid,
710         /// internal type used to indicate an unknown range type (defined term)
711         TRT_unknown = TRT_invalid,
712         /// DICOM Temporal Range Type: POINT
713         TRT_Point,
714         /// DICOM Temporal Range Type: MULTIPOINT
715         TRT_Multipoint,
716         /// DICOM Temporal Range Type: SEGMENT
717         TRT_Segment,
718         /// DICOM Temporal Range Type: MULTISEGMENT
719         TRT_Multisegment,
720         /// DICOM Temporal Range Type: BEGIN
721         TRT_Begin,
722         /// DICOM Temporal Range Type: END
723         TRT_End,
724         /// internal type used to mark the last entry
725         TRT_last = TRT_End
726     };
727 
728     /** SR continuity of content flag. Used for content item CONTAINER.
729      */
730     enum E_ContinuityOfContent
731     {
732         /// internal type used to indicate an error
733         COC_invalid,
734         /// DICOM enumerated value: SEPARATE
735         COC_Separate,
736         /// DICOM enumerated value: CONTINUOUS
737         COC_Continuous,
738         /// internal type used to mark the last entry
739         COC_last = COC_Continuous
740     };
741 
742     /** SR document preliminary flag
743      */
744     enum E_PreliminaryFlag
745     {
746         /// internal type used to indicate an error or the absence of this flag
747         PF_invalid,
748         /// DICOM enumerated value: PRELIMINARY
749         PF_Preliminary,
750         /// DICOM enumerated value: FINAL
751         PF_Final,
752         /// internal type used to mark the last entry
753         PF_last = PF_Final
754     };
755 
756     /** SR document completion flag
757      */
758     enum E_CompletionFlag
759     {
760         /// internal type used to indicate an error
761         CF_invalid,
762         /// DICOM enumerated value: PARTIAL
763         CF_Partial,
764         /// DICOM enumerated value: COMPLETE
765         CF_Complete,
766         /// internal type used to mark the last entry
767         CF_last = CF_Complete
768     };
769 
770     /** SR document verification flag
771      */
772     enum E_VerificationFlag
773     {
774         /// internal type used to indicate an error
775         VF_invalid,
776         /// DICOM enumerated value: UNVERIFIED
777         VF_Unverified,
778         /// DICOM enumerated value: VERIFIED
779         VF_Verified,
780         /// internal type used to mark the last entry
781         VF_last = VF_Verified
782     };
783 
784     /** Specific character set
785      */
786     enum E_CharacterSet
787     {
788         /// internal type used to indicate an error
789         CS_invalid,
790         /// internal type used to indicate an unknown/unsupported character set
791         CS_unknown = CS_invalid,
792         /// ISO 646 (ISO-IR 6): ASCII
793         CS_ASCII,
794         /// internal type used to indicate the default character set
795         CS_default = CS_ASCII,
796         /// ISO-IR 100: Latin alphabet No. 1
797         CS_Latin1,
798         /// ISO-IR 101: Latin alphabet No. 2
799         CS_Latin2,
800         /// ISO-IR 109: Latin alphabet No. 3
801         CS_Latin3,
802         /// ISO-IR 110: Latin alphabet No. 4
803         CS_Latin4,
804         /// ISO-IR 144: Cyrillic
805         CS_Cyrillic,
806         /// ISO-IR 127: Arabic
807         CS_Arabic,
808         /// ISO-IR 126: Greek
809         CS_Greek,
810         /// ISO-IR 138: Hebrew
811         CS_Hebrew,
812         /// ISO-IR 148: Latin alphabet No. 5
813         CS_Latin5,
814         /// ISO-IR 166: Thai
815         CS_Thai,
816         /// ISO-IR 13/87: Japanese (Katakana/Romaji/Kanji)
817         CS_Japanese,
818         /// ISO-IR 6/149: Korean (Hangul/Hanja)
819         CS_Korean,
820         /// ISO-IR 6/58: Chinese
821         CS_ChineseISO,
822         /// GB18030: Chinese
823         CS_ChineseGB18030,
824         /// GBK: Chinese
825         CS_ChineseGBK,
826         /// UTF-8: Unicode in UTF-8
827         CS_UTF8,
828         /// internal type used to mark the last entry
829         CS_last = CS_UTF8
830     };
831 
832     /** Code value type
833      */
834     enum E_CodeValueType
835     {
836         /// determine code value type automatically
837         CVT_auto,
838         /// short code value (VR=SH)
839         CVT_Short,
840         /// long code value (VR=UC)
841         CVT_Long,
842         /// URN code value (VR=UR)
843         CVT_URN
844     };
845 
846     /** Add node mode
847      */
848     enum E_AddMode
849     {
850         /// add new node after current one (sibling)
851         AM_afterCurrent,
852         /// add new node before current one (sibling)
853         AM_beforeCurrent,
854         /// add new node below current one (after last child)
855         AM_belowCurrent,
856         /// add new node below current one (before first child)
857         AM_belowCurrentBeforeFirstChild
858     };
859 
860 
861   // --- destructor ---
862 
863     /** destructor. (only needed to avoid compiler warnings)
864      */
865     virtual ~DSRTypes();
866 
867 
868   // --- conversion functions ---
869 
870     /** convert SR document type to SOP class UID
871      ** @param  documentType  SR document type to be converted
872      ** @return SOP class UID if type is valid, empty string otherwise (never NULL)
873      */
874     static const char *documentTypeToSOPClassUID(const E_DocumentType documentType);
875 
876     /** convert SR document type to modality
877      ** @param  documentType  SR document type to be converted
878      ** @return modality if type is valid, empty string otherwise (never NULL)
879      */
880     static const char *documentTypeToModality(const E_DocumentType documentType);
881 
882     /** convert SR document type to readable name.
883      *  Such a readable name is better suited for printing/rendering.
884      ** @param  documentType  SR document type to be converted
885      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
886      */
887     static const char *documentTypeToReadableName(const E_DocumentType documentType);
888 
889     /** convert SR document type to document title.
890      *  This document title is used for printing/rendering.
891      ** @param  documentType   SR document type to be converted
892      *  @param  documentTitle  reference to variable where the resulting string is stored
893      ** @return document title if type is valid, empty string otherwise (never NULL)
894      */
895     static const char *documentTypeToDocumentTitle(const E_DocumentType documentType,
896                                                    OFString &documentTitle);
897 
898     /** check whether a given SR document type requires the Enhanced General Equipment Module
899      ** @param  documentType  SR document type to be checked
900      ** @return OFTrue if the Enhanced General Equipment Module is required, OFFalse otherwise
901      */
902     static OFBool requiresEnhancedEquipmentModule(const E_DocumentType documentType);
903 
904     /** check whether a given SR document type requires the Timezone Module
905      ** @param  documentType  SR document type to be checked
906      ** @return OFTrue if the Timezone Module is required, OFFalse otherwise
907      */
908     static OFBool requiresTimezoneModule(const E_DocumentType documentType);
909 
910     /** check whether a given SR document type requires the Synchronization Module
911      ** @param  documentType  SR document type to be checked
912      ** @return OFTrue if the Synchronization Module is required, OFFalse otherwise
913      */
914     static OFBool requiresSynchronizationModule(const E_DocumentType documentType);
915 
916     /** check whether a given SR document type uses the SR Document Series Module
917      *  (instead of the Key Object Document Series Module)
918      ** @param  documentType  SR document type to be checked
919      ** @return OFTrue if the SR Document Series Module is used, OFFalse otherwise
920      */
921     static OFBool usesSRDocumentSeriesModule(const E_DocumentType documentType);
922 
923     /** check whether a given SR document type uses the Key Object Document Series Module
924      *  (instead of the SR Document Series Module)
925      ** @param  documentType  SR document type to be checked
926      ** @return OFTrue if the Key Object Document Series Module is used, OFFalse otherwise
927      */
928     static OFBool usesKeyObjectDocumentSeriesModule(const E_DocumentType documentType);
929 
930     /** check whether a given SR document type uses the SR Document General Module
931      *  (instead of the Key Object Document Module)
932      ** @param  documentType  SR document type to be checked
933      ** @return OFTrue if the SR Document General Module is used, OFFalse otherwise
934      */
935     static OFBool usesSRDocumentGeneralModule(const E_DocumentType documentType);
936 
937     /** check whether a given SR document type uses the Key Object Document Module
938      *  (instead of the SR Document General Module)
939      ** @param  documentType  SR document type to be checked
940      ** @return OFTrue if the Key Object Document Module is used, OFFalse otherwise
941      */
942     static OFBool usesKeyObjectDocumentModule(const E_DocumentType documentType);
943 
944     /** convert relationship type to DICOM defined term
945      ** @param  relationshipType  relationship type to be converted
946      ** @return defined term if type is valid, empty string otherwise (never NULL)
947      */
948     static const char *relationshipTypeToDefinedTerm(const E_RelationshipType relationshipType);
949 
950     /** convert relationship type to readable name.
951      *  Such a readable name is better suited for printing/rendering.
952      ** @param  relationshipType  relationship type to be converted
953      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
954      */
955     static const char *relationshipTypeToReadableName(const E_RelationshipType relationshipType);
956 
957     /** convert value type to DICOM defined term
958      ** @param  valueType  value type to be converted
959      ** @return defined term if type is valid, empty string otherwise (never NULL)
960      */
961     static const char *valueTypeToDefinedTerm(const E_ValueType valueType);
962 
963     /** convert value type to XML tag name
964      ** @param  valueType  value type to be converted
965      ** @return XML tag name if type is valid, "item" otherwise (never NULL)
966      */
967     static const char *valueTypeToXMLTagName(const E_ValueType valueType);
968 
969     /** convert value type to readable name.
970      *  Such a readable name is better suited for printing/rendering.
971      ** @param  valueType  value type to be converted
972      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
973      */
974     static const char *valueTypeToReadableName(const E_ValueType valueType);
975 
976     /** convert presentation state type to short name.
977      *  Such a short name (e.g. "GSPS") is better suited for printing/rendering than a UID.
978      ** @param  pstateType  presentation state type to be converted
979      ** @return short name if type is valid, "invalid ..." string otherwise (never NULL)
980      */
981     static const char *presentationStateTypeToShortName(const E_PresentationStateType pstateType);
982 
983     /** convert graphic type to DICOM enumerated value
984      ** @param  graphicType  graphic type to be converted
985      ** @return enumerated value if type is valid, empty string otherwise (never NULL)
986      */
987     static const char *graphicTypeToEnumeratedValue(const E_GraphicType graphicType);
988 
989     /** convert graphic type to readable name.
990      *  Such a readable name is better suited for printing/rendering.
991      ** @param  graphicType  graphic type to be converted
992      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
993      */
994     static const char *graphicTypeToReadableName(const E_GraphicType graphicType);
995 
996     /** convert graphic type (3D) to DICOM enumerated value
997      ** @param  graphicType  graphic type (3D) to be converted
998      ** @return enumerated value if type is valid, empty string otherwise (never NULL)
999      */
1000     static const char *graphicType3DToEnumeratedValue(const E_GraphicType3D graphicType);
1001 
1002     /** convert graphic type (3D) to readable name.
1003      *  Such a readable name is better suited for printing/rendering.
1004      ** @param  graphicType  graphic type (3D) to be converted
1005      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
1006      */
1007     static const char *graphicType3DToReadableName(const E_GraphicType3D graphicType);
1008 
1009     /** convert temporal range type to DICOM enumerated value
1010      ** @param  temporalRangeType  temporal range type to be converted
1011      ** @return enumerated value if type is valid, "invalid ..." string otherwise (never NULL)
1012      */
1013     static const char *temporalRangeTypeToEnumeratedValue(const E_TemporalRangeType temporalRangeType);
1014 
1015     /** convert temporal range type to readable name.
1016      *  Such a readable name is better suited for printing/rendering.
1017      ** @param  temporalRangeType  temporal range type to be converted
1018      ** @return readable name if type is valid, "invalid ..." string otherwise (never NULL)
1019      */
1020     static const char *temporalRangeTypeToReadableName(const E_TemporalRangeType temporalRangeType);
1021 
1022     /** convert continuity of content flag to DICOM enumerated value
1023      ** @param  continuityOfContent  continuity of content flag to be converted
1024      ** @return enumerated value if flag is valid, empty string otherwise (never NULL)
1025      */
1026     static const char *continuityOfContentToEnumeratedValue(const E_ContinuityOfContent continuityOfContent);
1027 
1028     /** convert preliminary flag to DICOM enumerated value
1029      ** @param  preliminaryFlag  preliminary flag to be converted
1030      ** @return enumerated value if flag is valid, empty string otherwise (never NULL)
1031      */
1032     static const char *preliminaryFlagToEnumeratedValue(const E_PreliminaryFlag preliminaryFlag);
1033 
1034     /** convert completion flag to DICOM enumerated value
1035      ** @param  completionFlag  completion flag to be converted
1036      ** @return enumerated value if successful, empty string otherwise (never NULL)
1037      */
1038     static const char *completionFlagToEnumeratedValue(const E_CompletionFlag completionFlag);
1039 
1040     /** convert verification flag to DICOM enumerated value
1041      ** @param  verificationFlag  verification flag to be converted
1042      ** @return enumerated value if flag is valid, empty string otherwise (never NULL)
1043      */
1044     static const char *verificationFlagToEnumeratedValue(const E_VerificationFlag verificationFlag);
1045 
1046     /** convert character set to DICOM defined term
1047      ** @param  characterSet  character set to be converted
1048      ** @return defined term if character set is valid, empty string otherwise (never NULL)
1049      */
1050     static const char *characterSetToDefinedTerm(const E_CharacterSet characterSet);
1051 
1052     /** convert character set to HTML name.
1053      *  This HTML (IANA) name is used to specify the character set in an HTML document.
1054      ** @param  characterSet  character set to be converted
1055      ** @return HTML name if character set is valid, empty string or "?" otherwise (never NULL)
1056      */
1057     static const char *characterSetToHTMLName(const E_CharacterSet characterSet);
1058 
1059     /** convert character set to XML name.
1060      *  This XML name is used to specify the character set in an XML document.
1061      ** @param  characterSet  character set to be converted
1062      ** @return XML name if character set is valid, empty string or "?" otherwise (never NULL)
1063      */
1064     static const char *characterSetToXMLName(const E_CharacterSet characterSet);
1065 
1066     /** convert SOP class UID to SR document type
1067      ** @param  sopClassUID  SOP class UID to be converted
1068      ** @return SR document type if successful, DSRTypes::DT_invalid otherwise
1069      */
1070     static E_DocumentType sopClassUIDToDocumentType(const OFString &sopClassUID);
1071 
1072     /** convert DICOM defined term to relationship type
1073      ** @param  definedTerm  defined term to be converted
1074      ** @return relationship type if successful, DSRTypes::RT_invalid otherwise
1075      */
1076     static E_RelationshipType definedTermToRelationshipType(const OFString &definedTerm);
1077 
1078     /** convert DICOM defined term to value type
1079      ** @param  definedTerm  defined term to be converted
1080      ** @return value type if successful, DSRTypes::VT_invalid otherwise
1081      */
1082     static E_ValueType definedTermToValueType(const OFString &definedTerm);
1083 
1084     /** convert SOP class UID to presentation state type
1085      ** @param  sopClassUID  SOP class UID to be converted
1086      ** @return presentation state type if successful, DSRTypes::PT_invalid otherwise
1087      */
1088     static E_PresentationStateType sopClassUIDToPresentationStateType(const OFString &sopClassUID);
1089 
1090     /** convert XML tag name to value type
1091      ** @param  xmlTagName  XML tag name to be converted
1092      ** @return value type if successful, DSRTypes::VT_invalid otherwise
1093      */
1094     static E_ValueType xmlTagNameToValueType(const OFString &xmlTagName);
1095 
1096     /** convert DICOM enumerated value to graphic type
1097      ** @param  enumeratedValue  enumerated value to be converted
1098      ** @return graphic type if successful, DSRTypes::GT_invalid otherwise
1099      */
1100     static E_GraphicType enumeratedValueToGraphicType(const OFString &enumeratedValue);
1101 
1102     /** convert DICOM enumerated value to graphic type (3D)
1103      ** @param  enumeratedValue  enumerated value to be converted
1104      ** @return graphic type if successful, DSRTypes::GT3_invalid otherwise
1105      */
1106     static E_GraphicType3D enumeratedValueToGraphicType3D(const OFString &enumeratedValue);
1107 
1108     /** convert DICOM enumerated value to temporal range type
1109      ** @param  enumeratedValue  enumerated value to be converted
1110      ** @return temporal range type if successful, DSRTypes::TRT_invalid otherwise
1111      */
1112     static E_TemporalRangeType enumeratedValueToTemporalRangeType(const OFString &enumeratedValue);
1113 
1114     /** convert DICOM enumerated value to continuity of content flag
1115      ** @param  enumeratedValue  enumerated value to be converted
1116      ** @return continuity of content flag type if successful, DSRTypes::COC_invalid otherwise
1117      */
1118     static E_ContinuityOfContent enumeratedValueToContinuityOfContent(const OFString &enumeratedValue);
1119 
1120     /** convert DICOM enumerated value to preliminary flag
1121      ** @param  enumeratedValue  enumerated value to be converted
1122      ** @return preliminary flag type if successful, DSRTypes::PF_invalid otherwise
1123      */
1124     static E_PreliminaryFlag enumeratedValueToPreliminaryFlag(const OFString &enumeratedValue);
1125 
1126     /** convert DICOM enumerated value to completion flag
1127      ** @param  enumeratedValue  enumerated value to be converted
1128      ** @return completion flag type if successful, DSRTypes::CF_invalid otherwise
1129      */
1130     static E_CompletionFlag enumeratedValueToCompletionFlag(const OFString &enumeratedValue);
1131 
1132     /** convert DICOM enumerated value to verification flag
1133      ** @param  enumeratedValue  enumerated value to be converted
1134      ** @return verification flag type if successful, DSRTypes::VF_invalid otherwise
1135      */
1136     static E_VerificationFlag enumeratedValueToVerificationFlag(const OFString &enumeratedValue);
1137 
1138     /** convert DICOM defined term to character set.
1139      *  An empty defined term is mapped to DSRTypes::CS_default (which is ASCII).
1140      ** @param  definedTerm  defined term to be converted
1141      ** @return character set if successful, DSRTypes::CS_invalid otherwise
1142      */
1143     static E_CharacterSet definedTermToCharacterSet(const OFString &definedTerm);
1144 
1145 
1146   // --- misc helper functions ---
1147 
1148     /** check whether specified SR document type is supported by this library
1149      ** @param  documentType  SR document type to be checked
1150      ** @return status, OFTrue if SR document type is supported, OFFalse otherwise
1151      */
1152     static OFBool isDocumentTypeSupported(const E_DocumentType documentType);
1153 
1154     /** get current date in DICOM 'DA' format. (YYYYMMDD)
1155      ** @param  dateString  string used to store the current date.
1156      *                      ('19000101' if current date could not be retrieved)
1157      ** @return resulting character string (see 'dateString')
1158      */
1159     static const OFString &currentDate(OFString &dateString);
1160 
1161     /** get current time in DICOM 'TM' format. (HHMMSS)
1162      ** @param  timeString  string used to store the current time
1163      *                      ('000000' if current time could not be retrieved)
1164      ** @return resulting character string (see 'timeString')
1165      */
1166     static const OFString &currentTime(OFString &timeString);
1167 
1168     /** get current date and time in DICOM 'DT' format. (YYYYMMDDHHMMSS)
1169      *  The optional UTC notation (e.g. +0100) as well as the optional fractional second
1170      *  part are currently not supported.
1171      ** @param  dateTimeString  string used to store the current date and time
1172      *                          ('19000101000000' if current date/time could not
1173      *                           be retrieved)
1174      ** @return resulting character string (see 'dateTimeString')
1175      */
1176     static const OFString &currentDateTime(OFString &dateTimeString);
1177 
1178     /** get local timezone in DICOM format. (&ZZXX)
1179      ** @param  timezoneString  string used to store the local timezone
1180      *                          ('+0000' if timezone could not be retrieved)
1181      ** @return resulting character string (see 'timezoneString')
1182      */
1183     static const OFString &localTimezone(OFString &timezoneString);
1184 
1185     /** convert DICOM date string to readable format.
1186      *  The ISO format "YYYY-MM-DD" is used for the readable format.
1187      ** @param  dicomDate     date in DICOM DA format (YYYYMMDD)
1188      *  @param  readableDate  reference to variable where the resulting string is stored
1189      ** @return reference to resulting string (might be empty)
1190      */
1191     static const OFString &dicomToReadableDate(const OFString &dicomDate,
1192                                                OFString &readableDate);
1193 
1194     /** convert DICOM time string to readable format.
1195      *  The ISO format "HH:MM" or "HH:MM:SS" (if seconds are available) is used for the
1196      *  readable format.
1197      ** @param  dicomTime     time in DICOM TM format (HHMM or HHMMSS...)
1198      *  @param  readableTime  reference to variable where the resulting string is stored
1199      ** @return reference to resulting string (might be empty)
1200      */
1201     static const OFString &dicomToReadableTime(const OFString &dicomTime,
1202                                                OFString &readableTime);
1203 
1204     /** convert DICOM date time string to readable format.
1205      *  The format "YYYY-MM-DD, HH:MM" or "YYYY-MM-DD, HH:MM:SS" is used for the readable format.
1206      ** @param  dicomDateTime     time in DICOM DT format (YYYYMMDDHHMMSS...). Possible suffixes
1207      *                            (fractional second or UTC notation) are currently ignored.
1208      *  @param  readableDateTime  reference to variable where the resulting string is stored
1209      ** @return reference to resulting string (might be empty)
1210      */
1211     static const OFString &dicomToReadableDateTime(const OFString &dicomDateTime,
1212                                                    OFString &readableDateTime);
1213 
1214     /** convert DICOM person name to readable format.
1215      *  The format "<prefix> <first_name> <middle_name> <last_name>, <suffix>" is used for the
1216      *  readable format.
1217      *  Please note that only the first component group (characters before the first '=') of
1218      *  the DICOM person name is used - see DcmPersonName::getNameComponents() for details.
1219      ** @param  dicomPersonName     person name in DICOM PN format (ln^fn^mn^p^s)
1220      *  @param  readablePersonName  reference to variable where the resulting string is stored
1221      ** @return reference to resulting string (might be empty)
1222      */
1223     static const OFString &dicomToReadablePersonName(const OFString &dicomPersonName,
1224                                                      OFString &readablePersonName);
1225 
1226     /** convert DICOM person name to XML format.
1227      *  The tags \<prefix\>, \<first\>, \<middle\>, \<last\> and \<suffix\> are used for the XML
1228      *  format of a person name.  The string is automatically converted to the markup notation
1229      *  (see convertToMarkupString()).  Two tags are separated by a newline.
1230      *  Please note that only the first component group (characters before the first '=') of
1231      *  the DICOM person name is used - see DcmPersonName::getNameComponents() for details.
1232      ** @param  dicomPersonName  person name in DICOM PN format (ln^fn^mn^p^s)
1233      *  @param  xmlPersonName    reference to variable where the resulting string is stored
1234      *  @param  writeEmptyValue  optional flag indicating whether an empty value should be written
1235      ** @return reference to resulting string (might be empty)
1236      */
1237     static const OFString &dicomToXMLPersonName(const OFString &dicomPersonName,
1238                                                 OFString &xmlPersonName,
1239                                                 const OFBool writeEmptyValue = OFFalse);
1240 
1241     /** convert unsigned integer number to character string
1242      ** @param  number       unsigned integer number to be converted
1243      *  @param  stringValue  character string used to store the result
1244      ** @return pointer to the first character of the resulting string
1245      *          (may be NULL if 'string' was NULL)
1246      */
1247     static const char *numberToString(const size_t number,
1248                                       char *stringValue);
1249 
1250     /** convert string to unsigned integer number
1251      ** @param  stringValue  character string to be converted
1252      ** @return resulting unsigned integer number if successful, 0 otherwise
1253      */
1254     static size_t stringToNumber(const char *stringValue);
1255 
1256     /** convert character string to print string.
1257      *  This method is used to convert character strings for text "print" output.  Newline characters
1258      *  "\n" are replaced by "\\n", return characters "\r" by "\\r", etc.
1259      ** @param  sourceString  source string to be converted
1260      *  @param  printString   reference to variable where the result should be stored
1261      ** @return reference to resulting 'printString' (might be empty if 'sourceString' was empty)
1262      */
1263     static const OFString &convertToPrintString(const OFString &sourceString,
1264                                                 OFString &printString);
1265 
1266     /** convert character string to HTML mnenonic string.
1267      *  Characters with special meaning for HTML (e.g. '<' and '&') are replace by the corresponding
1268      *  mnenonics (e.g. "&lt;" and "&amp;").
1269      *  If flag DSRTypes::HF_convertNonASCIICharacters is set, all characters > #127 are also converted
1270      *  (useful if only HTML 3.2 is supported which does not allow to specify the character set).
1271      ** @param  sourceString     source string to be converted
1272      *  @param  markupString     reference to variable where the result should be stored
1273      *  @param  flags            optional flags, only checking DSRTypes::HF_convertNonASCIICharacters,
1274      *                           DSRTypes::HF_HTML32Compatibility and DSRTypes::HF_XHTML11Compatibility
1275      *  @param  newlineAllowed   optional flag indicating whether newlines are allowed or not.
1276      *                           If they are allowed the text "<br>" is used, "&para;" otherwise.
1277      *                           The following combinations are accepted: LF, CR, LF CR, CF LF.
1278      ** @return reference to resulting 'markupString' (might be empty if 'sourceString' was empty)
1279      */
1280     static const OFString &convertToHTMLString(const OFString &sourceString,
1281                                                OFString &markupString,
1282                                                const size_t flags = 0,
1283                                                const OFBool newlineAllowed = OFFalse);
1284 
1285     /** convert character string to XML mnenonic string.
1286      *  Characters with special meaning for XML (e.g. '<' and '&') are replace by the
1287      *  corresponding mnenonics (e.g. "&lt;" and "&amp;").
1288      ** @param  sourceString  source string to be converted
1289      *  @param  markupString  reference to variable where the result should be stored
1290      ** @return reference to resulting 'markupString' (might be empty if 'sourceString' was empty)
1291      */
1292     static const OFString &convertToXMLString(const OFString &sourceString,
1293                                               OFString &markupString);
1294 
1295     /** check string for valid reference (as used for by-reference relationships).
1296      *  The string should be non-empty and consist of integer numbers only separated by a "." where
1297      *  the first and the last character of the string are always figures (0..9). Example: 1 or 1.2.3.
1298      *  Both the integer number 0 and a leading 0 for the numbers are forbidden.
1299      ** @param  stringValue  character string to be checked
1300      ** @result OFTrue if 'string' conforms to UID format, OFFalse otherwise
1301      */
1302     static OFBool checkForValidReference(const OFString &stringValue);
1303 
1304     /** create specified SR IOD content relationship constraint checker object.
1305      *  Please note that the created object has to be deleted by the caller.
1306      ** @param  documentType  associated SR document type for which the checker object is created
1307      ** @return pointer to new IOD checker object if successful, NULL if document type is not supported
1308      */
1309     static DSRIODConstraintChecker *createIODConstraintChecker(const E_DocumentType documentType);
1310 
1311     /** create specified document tree node.
1312      *  This is a shortcut and the only location where document tree nodes are created.
1313      *  It facilitates the introduction of new relationship/value types and the maintenance.
1314      ** @param  relationshipType  relationship type of the node to be created
1315      *  @param  valueType         value type of the node to be created
1316      ** @return pointer to the new document tree node if successful, NULL otherwise
1317      */
1318     static DSRDocumentTreeNode *createDocumentTreeNode(const E_RelationshipType relationshipType,
1319                                                        const E_ValueType valueType);
1320 
1321 
1322   // --- DICOM data structure access functions ---
1323 
1324     /** add given element to the dataset.
1325      *  The element is only added if 'result' is EC_Normal and the 'delem' pointer is not NULL.
1326      ** @param  result      reference to status variable (checked before adding and updated afterwards!)
1327      *  @param  dataset     reference to DICOM dataset to which the element should be added
1328      *  @param  delem       pointer to DICOM element which should be added. deleted if not inserted.
1329      *  @param  vm          value multiplicity (according to the data dictionary) to be checked for.
1330      *                      (See DcmElement::checkVM() for a list of valid values.)
1331      *                      Interpreted as cardinality (number of items) for sequence attributes.
1332      *  @param  type        value type (valid value: "1", "2" or something else which is not checked)
1333      *  @param  moduleName  optional module name to be printed (default: "SR document" if NULL)
1334      ** @return current value of 'result', EC_Normal if successful, an error code otherwise
1335      */
1336     static OFCondition addElementToDataset(OFCondition &result,
1337                                            DcmItem &dataset,
1338                                            DcmElement *delem,
1339                                            const OFString &vm,
1340                                            const OFString &type,
1341                                            const char *moduleName = NULL);
1342 
1343     /** remove given attribute from the sequence.
1344      *  All occurrences of the attribute in all items of the sequence are removed.
1345      ** @param  sequence  reference to DICOM sequence from which the attribute should be removed
1346      *  @param  tagKey    DICOM tag specifying the attribute which should be removed
1347      */
1348     static void removeAttributeFromSequence(DcmSequenceOfItems &sequence,
1349                                             const DcmTagKey &tagKey);
1350 
1351     /** get element from dataset
1352      ** @param  dataset  reference to DICOM dataset from which the element should be retrieved.
1353      *                   (Would be 'const' if the methods from 'dcmdata' would also be 'const'.)
1354      *  @param  delem    reference to DICOM element which should be retrieved.  The return value
1355      *                   is also stored in this parameter.
1356      ** @return status, EC_Normal if successful, an error code otherwise
1357      */
1358     static OFCondition getElementFromDataset(DcmItem &dataset,
1359                                              DcmElement &delem);
1360 
1361     /** get string value from element
1362      ** @param  delem  DICOM element from which the string value should be retrieved
1363      ** @return pointer to character string if successful, NULL otherwise
1364      */
1365     static const char *getStringValueFromElement(const DcmElement &delem);
1366 
1367    /** get string value from element.
1368     *  Please note that only the first element value is retrieved (in case of multiple values).
1369     ** @param  delem        DICOM element from which the string value should be retrieved
1370     *  @param  stringValue  reference to variable where the result should be stored
1371     ** @return reference character string if successful, empty string otherwise
1372     */
1373     static const OFString &getStringValueFromElement(const DcmElement &delem,
1374                                                      OFString &stringValue);
1375 
1376     /** get string value from element
1377      ** @param  delem        DICOM element from which the string value should be retrieved
1378      *  @param  stringValue  reference to variable in which the result should be stored
1379      *                       (This parameter is automatically cleared if an error occurs.)
1380      *  @param  pos          index of the value to get (0..vm-1), -1 for all components
1381      ** @return status, EC_Normal if successful, an error code otherwise
1382      */
1383     static OFCondition getStringValueFromElement(const DcmElement &delem,
1384                                                  OFString &stringValue,
1385                                                  const signed long pos);
1386 
1387     /** get string value from element and convert to "print" format.
1388      *  Please note that only the first element value is retrieved (in case of multiple values).
1389      ** @param  delem        DICOM element from which the string value should be retrieved
1390      *  @param  stringValue  reference to variable in which the result should be stored
1391      ** @return reference character string if successful, empty string otherwise
1392      */
1393     static const OFString &getPrintStringFromElement(const DcmElement &delem,
1394                                                      OFString &stringValue);
1395 
1396     /** get string value from element and convert to HTML/XML.
1397      *  Please note that only the first element value is retrieved (in case of multiple values).
1398      ** @param  delem            DICOM element from which the string value should be retrieved
1399      *  @param  stringValue      reference to variable in which the result should be stored
1400      *  @param  convertNonASCII  convert non-ASCII characters (> #127) to numeric value (&\#nnn;) if OFTrue
1401      ** @return reference character string if successful, empty string otherwise
1402      */
1403     static const OFString &getMarkupStringFromElement(const DcmElement &delem,
1404                                                       OFString &stringValue,
1405                                                       const OFBool convertNonASCII = OFFalse);
1406 
1407     /** get string value from dataset
1408      ** @param  dataset      DICOM dataset from which the string should be retrieved.
1409      *                       (Would be 'const' if the methods from 'dcmdata' would also be 'const'.)
1410      *  @param  tagKey       DICOM tag specifying the attribute from which the string should be retrieved
1411      *  @param  stringValue  reference to variable in which the result should be stored
1412      *                       (This parameter is automatically cleared if the tag could not be found.)
1413      *  @param  pos          index of the value to get (0..vm-1), -1 for all components
1414      ** @return status, EC_Normal if successful, an error code otherwise
1415      */
1416     static OFCondition getStringValueFromDataset(DcmItem &dataset,
1417                                                  const DcmTagKey &tagKey,
1418                                                  OFString &stringValue,
1419                                                  const signed long pos = 0);
1420 
1421     /** put string value to dataset
1422      ** @param  dataset      reference to DICOM dataset to which the string should be put.
1423      *  @param  tag          DICOM tag specifying the attribute to which the string should be put
1424      *  @param  stringValue  character string specifying the value to be set
1425      *  @param  allowEmpty   allow empty element to be inserted if OFTrue.
1426      *                       Do not insert empty element otherwise.
1427      ** @return status, EC_Normal if successful, an error code otherwise
1428      */
1429     static OFCondition putStringValueToDataset(DcmItem &dataset,
1430                                                const DcmTag &tag,
1431                                                const OFString &stringValue,
1432                                                const OFBool allowEmpty = OFTrue);
1433 
1434     /** check element value for correct value multiplicity and type.
1435      ** @param  delem            pointer to DICOM element to be checked (might be NULL)
1436      *  @param  tagKey           DICOM tag of the DICOM element the parameter 'delem' points to
1437      *  @param  vm               value multiplicity (according to the data dictionary) to be checked
1438      *                           for.  (See DcmElement::checkVM() for a list of valid values.)
1439      *                           Interpreted as cardinality (number of items) for sequence attributes.
1440      *  @param  type             value type (valid value: "1", "1C", "2", something else)
1441      *  @param  searchCond       optional flag indicating the status of a previous search() call
1442      *  @param  moduleName       optional module name to be printed (default: "SR document" if NULL)
1443      *  @param  acceptViolation  accept certain violations regarding the VR and VM if OFTrue.
1444      *                           A warning message will always be reported if the value in incorrect.
1445      ** @return OFTrue if element value is correct, OFFalse otherwise
1446      */
1447     static OFBool checkElementValue(DcmElement *delem,
1448                                     const DcmTagKey &tagKey,
1449                                     const OFString &vm,
1450                                     const OFString &type,
1451                                     const OFCondition &searchCond = EC_Normal,
1452                                     const char *moduleName = NULL,
1453                                     const OFBool acceptViolation = OFFalse);
1454 
1455     /** check element value for correct value multiplicity and type.
1456      ** @param  delem            DICOM element to be checked
1457      *  @param  vm               value multiplicity (according to the data dictionary) to be checked
1458      *                           for.  (See DcmElement::checkVM() for a list of valid values.)
1459      *                           Interpreted as cardinality (number of items) for sequence attributes.
1460      *  @param  type             value type (valid value: "1", "1C", "2", something else)
1461      *  @param  searchCond       optional flag indicating the status of a previous search() call
1462      *  @param  moduleName       optional module name to be printed (default: "SR document" if NULL)
1463      *  @param  acceptViolation  accept certain violations regarding the VR and VM if OFTrue.
1464      *                           A warning message will always be reported if the value in incorrect.
1465      ** @return OFTrue if element value is correct, OFFalse otherwise
1466      */
1467     static OFBool checkElementValue(DcmElement &delem,
1468                                     const OFString &vm,
1469                                     const OFString &type,
1470                                     const OFCondition &searchCond = EC_Normal,
1471                                     const char *moduleName = NULL,
1472                                     const OFBool acceptViolation = OFFalse);
1473 
1474     /** get element from dataset and check it for correct value multiplicity and type.
1475      ** @param  dataset          DICOM dataset from which the element should be retrieved.  (Would be
1476      *                           'const' if the methods from 'dcmdata' would also be 'const'.)
1477      *  @param  delem            DICOM element used to store the value (always creates a copy!)
1478      *  @param  vm               value multiplicity (according to the data dictionary) to be checked
1479      *                           for.  (See DcmElement::checkVM() for a list of valid values.)
1480      *                           Interpreted as cardinality (number of items) for sequence attributes.
1481      *  @param  type             value type (valid value: "1", "1C", "2", something else which is not
1482      *                           checked)
1483      *  @param  moduleName       optional module name to be printed (default: "SR document" if NULL)
1484      *  @param  acceptViolation  accept certain violations regarding the VR and VM if OFTrue.
1485      *                           A warning message will always be reported if the value in incorrect.
1486      ** @return status, EC_Normal if element could be retrieved and value is correct, an error code
1487      *          otherwise
1488      */
1489     static OFCondition getAndCheckElementFromDataset(DcmItem &dataset,
1490                                                      DcmElement &delem,
1491                                                      const OFString &vm,
1492                                                      const OFString &type,
1493                                                      const char *moduleName = NULL,
1494                                                      const OFBool acceptViolation = OFFalse);
1495 
1496     /** get string value from dataset and check it for correct value multiplicity and type.
1497      ** @param  dataset          DICOM dataset from which the element should be retrieved.  (Would be
1498      *                           'const' if the methods from 'dcmdata' would also be 'const'.)
1499      *  @param  tagKey           DICOM tag specifying the attribute from which the string should be
1500      *                           retrieved
1501      *  @param  stringValue      reference to variable in which the result should be stored.
1502      *                           (This parameter is automatically cleared if the tag could not be found.
1503      *                           It is not cleared if the retrieved string is invalid, e.g. violates VR
1504      *                           or VM definition.)
1505      *  @param  vm               value multiplicity (according to the data dictionary) to be checked
1506      *                           for.  (See DcmElement::checkVM() for a list of valid values.)
1507      *                           Interpreted as cardinality (number of items) for sequence attributes.
1508      *  @param  type             value type (valid value: "1", "1C", "2", something else which is not
1509      *                           checked)
1510      *  @param  moduleName       optional module name to be printed (default: "SR document" if NULL)
1511      *  @param  acceptViolation  accept certain violations regarding the VR and VM if OFTrue.
1512      *                           A warning message will always be reported if the value in incorrect.
1513      ** @return status, EC_Normal if element could be retrieved and value is correct, an error code
1514      *          otherwise
1515      */
1516     static OFCondition getAndCheckStringValueFromDataset(DcmItem &dataset,
1517                                                          const DcmTagKey &tagKey,
1518                                                          OFString &stringValue,
1519                                                          const OFString &vm,
1520                                                          const OFString &type,
1521                                                          const char *moduleName = NULL,
1522                                                          const OFBool acceptViolation = OFFalse);
1523 
1524   // --- output functions ---
1525 
1526     /** print the warning message that the current content item is invalid/incomplete.
1527      *  The value type (for DEBUG mode also the node ID) is added if the 'node' if specified.
1528      *  @param  action    text describing the current action (e.g. 'Reading'), 'Processing' if NULL
1529      *  @param  node      pointer to document tree node for which the message should be printed
1530      *  @param  location  position of the affected content item (e.g. '1.2.3', not printed if NULL)
1531      */
1532     static void printInvalidContentItemMessage(const char *action,
1533                                                const DSRDocumentTreeNode *node,
1534                                                const char *location = NULL);
1535 
1536     /** print an error message for the current content item.
1537      *  The value type (for DEBUG mode also the node ID) is added if the 'node' if specified.
1538      *  @param  action    text describing the current action (e.g. 'Reading'), 'Processing' if NULL
1539      *  @param  result    status used to print more information on the error (no message if EC_Normal)
1540      *  @param  node      pointer to document tree node for which the message should be printed
1541      *  @param  location  position of the affected content item (e.g. '1.2.3', not printed if NULL)
1542      */
1543     static void printContentItemErrorMessage(const char *action,
1544                                              const OFCondition &result,
1545                                              const DSRDocumentTreeNode *node,
1546                                              const char *location = NULL);
1547 
1548     /** print a warning message that an unknown/unsupported value has been determined
1549      *  @param  valueName  name of the unknown/unsupported value
1550      *  @param  readValue  value that has been read (optional)
1551      *  @param  action     text describing the current action (default: 'Reading'), 'Processing' if NULL
1552      */
1553     static void printUnknownValueWarningMessage(const char *valueName,
1554                                                 const char *readValue = NULL,
1555                                                 const char *action = "Reading");
1556 
1557     /** write string value to XML output stream.
1558      *  The output looks like this: "<" tagName ">" stringValue "</" tagName ">"
1559      ** @param  stream           output stream to which the XML document is written
1560      *  @param  stringValue      string value to be written
1561      *  @param  tagName          name of the XML tag used to surround the string value
1562      *  @param  writeEmptyValue  optional flag indicating whether an empty value should be written
1563      ** @return OFTrue if tag/value has been written, OFFalse otherwise
1564      */
1565     static OFBool writeStringValueToXML(STD_NAMESPACE ostream &stream,
1566                                         const OFString &stringValue,
1567                                         const OFString &tagName,
1568                                         const OFBool writeEmptyValue = OFFalse);
1569 
1570     /** write string value from DICOM element to XML output stream.
1571      *  The output looks like this: "<" tagName ">" stringValue "</" tagName ">"
1572      *  For elements with DICOM VR=PN the function dicomToXMLPersonName() is used internally.
1573      ** @param  stream           output stream to which the XML document is written
1574      *  @param  delem            DICOM element from which the value is retrieved
1575      *  @param  tagName          name of the XML tag used to surround the string value
1576      *  @param  writeEmptyValue  optional flag indicating whether an empty value should be written
1577      ** @return OFTrue if tag/value has been written, OFFalse otherwise
1578      */
1579     static OFBool writeStringFromElementToXML(STD_NAMESPACE ostream &stream,
1580                                               DcmElement &delem,
1581                                               const OFString &tagName,
1582                                               const OFBool writeEmptyValue = OFFalse);
1583 
1584     /** create an HTML annex entry with hyperlinks.
1585      *  A reference text is added to the main document and a new annex entry to the document annex
1586      *  with HTML hyperlinks between both.  Example for a reference: '[for details see Annex 1]'
1587      ** @param  docStream      output stream used for the main document
1588      *  @param  annexStream    output stream used for the document annex
1589      *  @param  referenceText  optional text added to the main document (e.g. 'for details see')
1590      *  @param  annexNumber    reference to the variable where the current annex number is stored.
1591      *                         Value is increased automatically by 1 after the new entry has been added.
1592      *  @param  flags          optional flag used to customize the output (see DSRTypes::HF_xxx)
1593      ** @return current annex number after the new entry has been added
1594      */
1595     static size_t createHTMLAnnexEntry(STD_NAMESPACE ostream &docStream,
1596                                        STD_NAMESPACE ostream &annexStream,
1597                                        const OFString &referenceText,
1598                                        size_t &annexNumber,
1599                                        const size_t flags = 0);
1600 
1601     /** create an HTML footnote with hyperlinks
1602      ** @param  docStream       output stream used for the main document
1603      *  @param  footnoteStream  output stream used for the footnote text
1604      *  @param  footnoteNumber  reference to the variable where the current footnote number is stored.
1605      *                          Value is increased automatically by 1 after the new entry has been added.
1606      *  @param  nodeID          unique numerical identifier of the current node for which this footnote
1607      *                          is created.  Used to create a unique name for the hyperlink.
1608      *  @param  flags           optional flag used to customize the output (see DSRTypes::HF_xxx)
1609      ** @return current footnote number after the new entry has been added
1610      */
1611     static size_t createHTMLFootnote(STD_NAMESPACE ostream &docStream,
1612                                      STD_NAMESPACE ostream &footnoteStream,
1613                                      size_t &footnoteNumber,
1614                                      const size_t nodeID,
1615                                      const size_t flags = 0);
1616 
1617     /** append one output stream to another.
1618      ** @param  mainStream  stream to which the other should be added
1619      *  @param  tempStream  (string) stream to be added to the other
1620      *  @param  heading     (optional) string which is added to the 'mainStream' before the 'tempStream'.
1621      *                      This string is only added if 'tempStream' is not empty.
1622      ** @return status, EC_Normal if stream has been added successfully, an error code otherwise
1623      */
1624     static OFCondition appendStream(STD_NAMESPACE ostream &mainStream,
1625                                     OFOStringStream &tempStream,
1626                                     const char *heading = NULL);
1627 };
1628 
1629 
1630 #endif
1631