1 /*
2  *
3  *  Copyright (C) 2000-2017, 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: DSRCompositeReferenceValue
20  *
21  */
22 
23 
24 #ifndef DSRCOMVL_H
25 #define DSRCOMVL_H
26 
27 #include "dcmtk/config/osconfig.h"   /* make sure OS specific configuration is included first */
28 
29 #include "dcmtk/dcmsr/dsrtypes.h"
30 
31 
32 /*---------------------*
33  *  class declaration  *
34  *---------------------*/
35 
36 /** Class for composite reference values
37  */
38 class DCMTK_DCMSR_EXPORT DSRCompositeReferenceValue
39 {
40     // allow access to getValuePtr()
41     friend class DSRContentItem;
42 
43   public:
44 
45     /** default constructor
46      */
47     DSRCompositeReferenceValue();
48 
49     /** constructor
50      ** @param  sopClassUID     referenced SOP class UID of the composite object.
51      *                          (VR=UI, mandatory)
52      *  @param  sopInstanceUID  referenced SOP instance UID of the composite object.
53      *                          (VR=UI, mandatory)
54      *  @param  check           if enabled, check 'sopClassUID' and 'sopInstanceUID' for
55      *                          validity before setting them.  See checkXXX() for details.
56      *                          Empty values are never accepted.
57      */
58     DSRCompositeReferenceValue(const OFString &sopClassUID,
59                                const OFString &sopInstanceUID,
60                                const OFBool check = OFTrue);
61 
62     /** copy constructor
63      ** @param  referenceValue  reference value to be copied (not checked !)
64      */
65     DSRCompositeReferenceValue(const DSRCompositeReferenceValue &referenceValue);
66 
67     /** destructor
68      */
69     virtual ~DSRCompositeReferenceValue();
70 
71     /** assignment operator
72      ** @param  referenceValue  reference value to be copied (not checked !)
73      ** @return reference to this reference value after 'referenceValue' has been copied
74      */
75     DSRCompositeReferenceValue &operator=(const DSRCompositeReferenceValue &referenceValue);
76 
77     /** comparison operator "equal"
78      ** @param  referenceValue  reference value that should be compared to the current one
79      ** @return OFTrue if both composite reference values are equal, OFFalse otherwise
80      */
81     OFBool operator==(const DSRCompositeReferenceValue &referenceValue) const;
82 
83     /** comparison operator "not equal"
84      ** @param  referenceValue  reference value that should be compared to the current one
85      ** @return OFTrue if both composite reference values are not equal, OFFalse otherwise
86      */
87     OFBool operator!=(const DSRCompositeReferenceValue &referenceValue) const;
88 
89     /** clear all internal variables.
90      *  Since an empty reference value is invalid the reference becomes invalid afterwards.
91      */
92     virtual void clear();
93 
94     /** check whether the current reference value is valid.
95      *  The reference value is valid if SOP class UID and SOP instance UID are valid.  See
96      *  checkSOPClassUID() and checkSOPInstanceUID() methods for details.
97      ** @return OFTrue if reference value is valid, OFFalse otherwise
98      */
99     virtual OFBool isValid() const;
100 
101     /** check whether the current reference value is empty.
102      *  Checks whether both mandatory UIDs of the reference value are empty.
103      ** @return OFTrue if value is empty, OFFalse otherwise
104      */
105     virtual OFBool isEmpty() const;
106 
107     /** check whether the current reference value is complete, i.e.\ whether both
108      *  mandatory UIDs are non-empty.  This is just a basic check that might be useful
109      *  for "validating" input data.  See isValid() for a more sophisticated way of
110      *  checking the current reference value.
111      ** @return OFTrue if value is complete, OFFalse otherwise
112      */
113     virtual OFBool isComplete() const;
114 
115     /** print reference value.
116      *  The output of a typical composite reference value looks like this: (BasicTextSR,"1.2.3").
117      *  If the SOP class UID is unknown, the UID is printed instead of the related name.
118      ** @param  stream  output stream to which the reference value should be printed
119      *  @param  flags   flag used to customize the output (see DSRTypes::PF_xxx)
120      ** @return status, EC_Normal if successful, an error code otherwise
121      */
122     virtual OFCondition print(STD_NAMESPACE ostream &stream,
123                               const size_t flags) const;
124 
125     /** read reference value from XML document
126      ** @param  doc     document containing the XML file content
127      *  @param  cursor  cursor pointing to the starting node
128      *  @param  flags   flag used to customize the reading process (see DSRTypes::XF_xxx)
129      ** @return status, EC_Normal if successful, an error code otherwise
130      */
131     virtual OFCondition readXML(const DSRXMLDocument &doc,
132                                 DSRXMLCursor cursor,
133                                 const size_t flags);
134 
135     /** write reference value in XML format
136      ** @param  stream  output stream to which the XML document is written
137      *  @param  flags   flag used to customize the output (see DSRTypes::XF_xxx)
138      ** @return status, EC_Normal if successful, an error code otherwise
139      */
140     virtual OFCondition writeXML(STD_NAMESPACE ostream &stream,
141                                  const size_t flags) const;
142 
143     /** read referenced SOP sequence from dataset.
144      *  The number of items within the sequence is checked.  If error/warning output are
145      *  enabled, a warning message is printed if the sequence is absent or contains more than
146      *  one item.
147      ** @param  dataset  DICOM dataset from which the sequence should be read
148      *  @param  tagKey   DICOM tag specifying the attribute (= sequence) that should be read
149      *  @param  type     value type of the sequence (valid value: "1", "2", something else)
150      *                   This parameter is used for checking purpose, any difference is reported.
151      *  @param  flags    flag used to customize the reading process (see DSRTypes::RF_xxx)
152      ** @return status, EC_Normal if successful, an error code otherwise
153      */
154     virtual OFCondition readSequence(DcmItem &dataset,
155                                      const DcmTagKey &tagKey,
156                                      const OFString &type,
157                                      const size_t flags);
158 
159     /** write referenced SOP sequence to dataset.
160      *  If the value is empty an empty sequence (without any items) is written.
161      ** @param  dataset  DICOM dataset to which the sequence should be written
162      *  @param  tagKey   DICOM tag specifying the attribute (= sequence) that should be written
163      ** @return status, EC_Normal if successful, an error code otherwise
164      */
165     virtual OFCondition writeSequence(DcmItem &dataset,
166                                       const DcmTagKey &tagKey) const;
167 
168     /** render composite reference value in HTML/XHTML format
169      ** @param  docStream    output stream to which the main HTML/XHTML document is written
170      *  @param  annexStream  output stream to which the HTML/XHTML document annex is written
171      *  @param  annexNumber  reference to the variable where the current annex number is stored.
172      *                       Value is increased automatically by 1 after a new entry has been added.
173      *  @param  flags        flag used to customize the output (see DSRTypes::HF_xxx)
174      ** @return status, EC_Normal if successful, an error code otherwise
175      */
176     virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
177                                    STD_NAMESPACE ostream &annexStream,
178                                    size_t &annexNumber,
179                                    const size_t flags) const;
180 
181     /** get SOP class UID
182      ** @return current SOP class UID (might be invalid or an empty string)
183      */
getSOPClassUID()184     inline const OFString &getSOPClassUID() const
185     {
186         return SOPClassUID;
187     }
188 
189     /** get name associated with the SOP class UID (if any)
190      ** @param  defaultName  string value that is returned if the SOP class UID is unknown
191      ** @return name associated with the current SOP class UID (might be empty, e.g. in case
192      *          the SOP class UID is empty or 'defaultName' is an empty string)
193      */
194     const OFString getSOPClassName(const OFString &defaultName = "unknown SOP Class UID") const;
195 
196     /** get SOP instance UID
197      ** @return current SOP instance UID (might be invalid or an empty string)
198      */
getSOPInstanceUID()199     inline const OFString &getSOPInstanceUID() const
200     {
201         return SOPInstanceUID;
202     }
203 
204     /** get reference to composite reference value
205      ** @return reference to composite reference value
206      */
getValue()207     inline const DSRCompositeReferenceValue &getValue() const
208     {
209         return *this;
210     }
211 
212     /** get copy of composite reference value
213      ** @param  referenceValue  reference to variable in which the value should be stored
214      ** @return status, EC_Normal if successful, an error code otherwise
215      */
216     OFCondition getValue(DSRCompositeReferenceValue &referenceValue) const;
217 
218     /** set composite reference value.
219      *  Before setting the reference, it is usually checked.  If the value is invalid, the
220      *  current value is not replaced and remains unchanged.
221      ** @param  referenceValue  value to be set
222      *  @param  check           if enabled, check value for validity before setting it.
223      *                          See checkXXX() for details.  Empty values are never accepted.
224      ** @return status, EC_Normal if successful, an error code otherwise
225      */
226     OFCondition setValue(const DSRCompositeReferenceValue &referenceValue,
227                          const OFBool check = OFTrue);
228 
229     /** set SOP class UID and SOP instance UID value.
230      *  Before setting the values, they are usually checked.  If the value pair is invalid
231      *  the current value pair is not replaced and remains unchanged.
232      ** @param  sopClassUID     referenced SOP class UID to be set. (VR=UI, mandatory)
233      *  @param  sopInstanceUID  referenced SOP instance UID to be set. (VR=UI, mandatory)
234      *  @param  check           if enabled, check 'sopClassUID' and 'sopInstanceUID' for
235      *                          validity before setting them.  See checkXXX() for details.
236      *                          Empty values are never accepted.
237      ** @return status, EC_Normal if successful, an error code otherwise
238      */
239     OFCondition setReference(const OFString &sopClassUID,
240                              const OFString &sopInstanceUID,
241                              const OFBool check = OFTrue);
242 
243     /** set SOP class UID and SOP instance UID value from dataset.
244      *  Internally, the methods setSOPClassUID() and setSOPInstanceUID() are called with the
245      *  given 'dataset' and the tags DCM_SOPClassUID and DCM_SOPInstanceUID, respectively.
246      *  I.e., the SOP class UID might be set even if the SOP instance UID value is invalid.
247      ** @param  dataset  DICOM dataset from which the UID values should be retrieved
248      *  @param  check    if enabled, check retrieved UID values for validity before setting
249      *                   them.  See checkXXX() for details. Empty values are never accepted.
250      ** @return status, EC_Normal if successful, an error code otherwise
251      */
252     OFCondition setReference(DcmItem &dataset,
253                              const OFBool check = OFTrue);
254 
255     /** set SOP class UID value.
256      *  Before setting the value, it is usually checked.  If the value is invalid, the current
257      *  value is not replaced and remains unchanged.
258      ** @param  sopClassUID  SOP class UID to be set
259      *  @param  check        if enabled, check 'sopClassUID' for validity before setting it.
260      *                       See checkSOPClassUID() for details.  Am empty value is never
261      *                       accepted.
262      ** @return status, EC_Normal if successful, an error code otherwise
263      */
264     OFCondition setSOPClassUID(const OFString &sopClassUID,
265                                const OFBool check = OFTrue);
266 
267     /** set SOP class UID value from element.
268      *  Before setting the value, it is usually checked.  If the value is invalid, the current
269      *  value is not replaced and remains unchanged.
270      ** @param  delem  DICOM element from which the UID value should be retrieved
271      *  @param  pos    index of the value in case of multi-valued elements (0..vm-1)
272      *  @param  check  if enabled, check UID value for validity before setting it.  See
273      *                 checkSOPClassUID() for details.  An empty value is never accepted.
274      ** @return status, EC_Normal if successful, an error code otherwise
275      */
276     OFCondition setSOPClassUID(const DcmElement &delem,
277                                const unsigned long pos = 0,
278                                const OFBool check = OFTrue);
279 
280     /** set SOP class UID value from dataset.
281      *  Before setting the value, it is usually checked.  If the value is invalid, the current
282      *  value is not replaced and remains unchanged.
283      ** @param  dataset  DICOM dataset from which the UID value should be retrieved
284      *  @param  tagKey   DICOM tag specifying the attribute from which the value should be
285      *                   retrieved.  The search is limited to the top-level of the dataset.
286      *  @param  pos      index of the value in case of multi-valued elements (0..vm-1)
287      *  @param  check    if enabled, check UID value for validity before setting it.  See
288      *                   checkSOPClassUID() for details.  An empty value is never accepted.
289      ** @return status, EC_Normal if successful, an error code otherwise
290      */
291     OFCondition setSOPClassUID(DcmItem &dataset,
292                                const DcmTagKey &tagKey,
293                                const unsigned long pos = 0,
294                                const OFBool check = OFTrue);
295 
296     /** set SOP instance UID value.
297      *  Before setting the value, it is usually checked.  If the value is invalid, the current
298      *  value is not replaced and remains unchanged.
299      ** @param  sopInstanceUID  SOP instance UID to be set
300      *  @param  check           if enabled, check 'sopInstanceUID' for validity before setting
301      *                          it.  See checkSOPInstanceUID() for details.  An empty value is
302      *                          never accepted.
303      ** @return status, EC_Normal if successful, an error code otherwise
304      */
305     OFCondition setSOPInstanceUID(const OFString &sopInstanceUID,
306                                   const OFBool check = OFTrue);
307 
308     /** set SOP instance UID value from element.
309      *  Before setting the value, it is usually checked.  If the value is invalid, the current
310      *  value is not replaced and remains unchanged.
311      ** @param  delem  DICOM element from which the UID value should be retrieved
312      *  @param  pos    index of the value in case of multi-valued elements (0..vm-1)
313      *  @param  check  if enabled, check UID value for validity before setting it.  See
314      *                 checkSOPInstanceUID() for details.  An empty value is never accepted.
315      ** @return status, EC_Normal if successful, an error code otherwise
316      */
317     OFCondition setSOPInstanceUID(const DcmElement &delem,
318                                   const unsigned long pos = 0,
319                                   const OFBool check = OFTrue);
320 
321     /** set SOP instance UID value from dataset.
322      *  Before setting the value, it is usually checked.  If the value is invalid, the current
323      *  value is not replaced and remains unchanged.
324      ** @param  dataset  DICOM dataset from which the UID value should be retrieved
325      *  @param  tagKey   DICOM tag specifying the attribute from which the value should be
326      *                   retrieved.  The search is limited to the top-level of the dataset.
327      *  @param  pos      index of the value in case of multi-valued elements (0..vm-1)
328      *  @param  check    if enabled, check UID value for validity before setting it.  See
329      *                   checkSOPInstanceUID() for details.  An empty value is never accepted.
330      ** @return status, EC_Normal if successful, an error code otherwise
331      */
332     OFCondition setSOPInstanceUID(DcmItem &dataset,
333                                   const DcmTagKey &tagKey,
334                                   const unsigned long pos = 0,
335                                   const OFBool check = OFTrue);
336 
337 
338   protected:
339 
340     /** get pointer to reference value
341      ** @return pointer to reference value (never NULL)
342      */
getValuePtr()343     inline DSRCompositeReferenceValue *getValuePtr()
344     {
345         return this;
346     }
347 
348     /** read reference value from dataset
349      ** @param  dataset  DICOM dataset from which the value should be read
350      *  @param  flags    flag used to customize the reading process (see DSRTypes::RF_xxx)
351      ** @return status, EC_Normal if successful, an error code otherwise
352      */
353     virtual OFCondition readItem(DcmItem &dataset,
354                                  const size_t flags);
355 
356     /** write reference value to dataset
357      ** @param  dataset  DICOM dataset to which the value should be written
358      ** @return status, EC_Normal if successful, an error code otherwise
359      */
360     virtual OFCondition writeItem(DcmItem &dataset) const;
361 
362     /** check the specified SOP class UID for validity.
363      *  The only checks performed are that the UID is non-empty and that it conforms to the
364      *  corresponding VR (UI) and VM (1).  Derived classes should overwrite this method for
365      *  more specific tests (e.g. allowing only particular SOP classes).
366      ** @param  sopClassUID   SOP class UID to be checked
367      ** @return status, EC_Normal if value is valid, an error code otherwise
368      */
369     virtual OFCondition checkSOPClassUID(const OFString &sopClassUID) const;
370 
371     /** check the specified SOP instance UID for validity.
372      *  The only checks performed are that the UID is non-empty and that it conforms to the
373      *  corresponding VR (UI) and VM (1).  Derived classes should overwrite this method for
374      *  more specific tests.
375      *  @param  sopInstanceUID  SOP instance UID to be checked
376      ** @return status, EC_Normal if value is valid, an error code otherwise
377      */
378     virtual OFCondition checkSOPInstanceUID(const OFString &sopInstanceUID) const;
379 
380     /** check the currently stored reference value for validity.
381      *  See above checkXXX() methods for details.
382      ** @return status, EC_Normal if current value is valid, an error code otherwise
383      */
384     OFCondition checkCurrentValue() const;
385 
386     /// reference SOP class UID (VR=UI, type 1)
387     OFString SOPClassUID;
388     /// reference SOP instance UID (VR=UI, type 1)
389     OFString SOPInstanceUID;
390 };
391 
392 
393 #endif
394