1 /*
2  *
3  *  Copyright (C) 1998-2010, 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: dcmpstat
15  *
16  *  Author: Marco Eichelberg
17  *
18  *  Purpose:
19  *    classes: DVPSGraphicAnnotation_PList
20  *
21  */
22 
23 #include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmpstat/dvpsgal.h"
25 #include "dcmtk/dcmpstat/dvpsga.h"      /* for DVPSGraphicAnnotation */
26 #include "dcmtk/ofstd/ofstring.h"    /* for OFString */
27 #include "dcmtk/dcmpstat/dvpstx.h"      /* for DVPSTextObject */
28 #include "dcmtk/dcmpstat/dvpsgr.h"      /* for DVPSGraphicObject */
29 #include "dcmtk/dcmpstat/dvpsri.h"      /* for DVPSReferencedImage, needed by MSVC5 with STL */
30 
DVPSGraphicAnnotation_PList()31 DVPSGraphicAnnotation_PList::DVPSGraphicAnnotation_PList()
32 : list_()
33 {
34 }
35 
DVPSGraphicAnnotation_PList(const DVPSGraphicAnnotation_PList & arg)36 DVPSGraphicAnnotation_PList::DVPSGraphicAnnotation_PList(const DVPSGraphicAnnotation_PList &arg)
37 : list_()
38 {
39   OFListConstIterator(DVPSGraphicAnnotation *) first = arg.list_.begin();
40   OFListConstIterator(DVPSGraphicAnnotation *) last = arg.list_.end();
41   while (first != last)
42   {
43     list_.push_back((*first)->clone());
44     ++first;
45   }
46 }
47 
~DVPSGraphicAnnotation_PList()48 DVPSGraphicAnnotation_PList::~DVPSGraphicAnnotation_PList()
49 {
50   clear();
51 }
52 
clear()53 void DVPSGraphicAnnotation_PList::clear()
54 {
55   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
56   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
57   while (first != last)
58   {
59     delete (*first);
60     first = list_.erase(first);
61   }
62 }
63 
read(DcmItem & dset)64 OFCondition DVPSGraphicAnnotation_PList::read(DcmItem &dset)
65 {
66   OFCondition result = EC_Normal;
67   DcmStack stack;
68   DVPSGraphicAnnotation *newObject = NULL;
69   DcmSequenceOfItems *dseq=NULL;
70   DcmItem *ditem=NULL;
71 
72   if (EC_Normal == dset.search(DCM_GraphicAnnotationSequence, stack, ESM_fromHere, OFFalse))
73   {
74     dseq=(DcmSequenceOfItems *)stack.top();
75     if (dseq)
76     {
77       unsigned long numItems = dseq->card();
78       for (unsigned int i=0; i<numItems; i++)
79       {
80         ditem = dseq->getItem(i);
81         newObject = new DVPSGraphicAnnotation();
82         if (newObject && ditem)
83         {
84           result = newObject->read(*ditem);
85           list_.push_back(newObject);
86         } else result = EC_MemoryExhausted;
87       }
88     }
89   }
90 
91   return result;
92 }
93 
write(DcmItem & dset)94 OFCondition DVPSGraphicAnnotation_PList::write(DcmItem &dset)
95 {
96   if (list_.size()==0) return EC_Normal; // don't write empty Sequence
97 
98   OFCondition result = EC_Normal;
99   DcmSequenceOfItems *dseq=NULL;
100   DcmItem *ditem=NULL;
101 
102   dseq = new DcmSequenceOfItems(DCM_GraphicAnnotationSequence);
103   if (dseq)
104   {
105     OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
106     OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
107     while (first != last)
108     {
109       if (result==EC_Normal)
110       {
111         ditem = new DcmItem();
112         if (ditem)
113         {
114           result = (*first)->write(*ditem);
115           if (result==EC_Normal) dseq->insert(ditem); else delete ditem;
116         } else result = EC_MemoryExhausted;
117       }
118       ++first;
119     }
120     if (result==EC_Normal) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
121   } else result = EC_MemoryExhausted;
122   return result;
123 }
124 
125 
renameLayer(const char * oldName,const char * newName)126 void DVPSGraphicAnnotation_PList::renameLayer(const char *oldName, const char *newName)
127 {
128   if ((oldName==NULL)||(newName==NULL)) return;
129 
130   OFString aString(oldName);
131   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
132   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
133   while (first != last)
134   {
135     if (aString == (*first)->getAnnotationLayer())
136     {
137       (*first)->setAnnotationLayer(newName);
138     }
139     ++first;
140   }
141   return;
142 }
143 
removeLayer(const char * name)144 void DVPSGraphicAnnotation_PList::removeLayer(const char *name)
145 {
146   if (name==NULL) return;
147 
148   OFString aString(name);
149   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
150   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
151   while (first != last)
152   {
153     if (aString == (*first)->getAnnotationLayer())
154     {
155       delete (*first);
156       first = list_.erase(first);
157     } else ++first;
158   }
159   return;
160 }
161 
cleanupLayers()162 void DVPSGraphicAnnotation_PList::cleanupLayers()
163 {
164   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
165   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
166   while (first != last)
167   {
168     if ((*first)->isEmpty())
169     {
170       delete (*first);
171       first = list_.erase(first);
172     } else ++first;
173   }
174   return;
175 }
176 
177 
usesLayerName(const char * name)178 OFBool DVPSGraphicAnnotation_PList::usesLayerName(const char *name)
179 {
180   if (name==NULL) return OFFalse;
181 
182   OFString aString(name);
183   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
184   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
185   while (first != last)
186   {
187     if (aString == (*first)->getAnnotationLayer()) return OFTrue;
188     ++first;
189   }
190   return OFFalse;
191 }
192 
193 
getNumberOfTextObjects(const char * layer,const char * instanceUID,unsigned long frame)194 size_t DVPSGraphicAnnotation_PList::getNumberOfTextObjects(const char *layer, const char *instanceUID, unsigned long frame)
195 {
196   if (layer==NULL) return 0;
197 
198   size_t result = 0;
199   OFString aString(layer);
200   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
201   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
202   while (first != last)
203   {
204     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
205     {
206       result += (*first)->getNumberOfTextObjects();
207     }
208     ++first;
209   }
210   return result;
211 }
212 
getTextObject(const char * layer,const char * instanceUID,unsigned long frame,size_t idx)213 DVPSTextObject *DVPSGraphicAnnotation_PList::getTextObject(const char *layer, const char *instanceUID, unsigned long frame, size_t idx)
214 {
215   if (layer==NULL) return NULL;
216 
217   size_t tmp = 0;
218   OFString aString(layer);
219   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
220   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
221   while (first != last)
222   {
223     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
224     {
225       tmp = (*first)->getNumberOfTextObjects();
226       if (idx < tmp) return (*first)->getTextObject(idx); else idx -= tmp;
227     }
228     ++first;
229   }
230   return NULL;
231 }
232 
233 
addTextObject(const char * layer,const char * sopclassUID,const char * instanceUID,unsigned long frame,DVPSObjectApplicability applicability,DVPSTextObject * text)234 DVPSTextObject *DVPSGraphicAnnotation_PList::addTextObject(
235     const char *layer,
236     const char *sopclassUID,
237     const char *instanceUID,
238     unsigned long frame,
239     DVPSObjectApplicability applicability,
240     DVPSTextObject *text)
241 {
242   if (layer==NULL) return NULL;
243 
244   if (text==NULL)
245   {
246     text = new DVPSTextObject();
247   }
248   if (text==NULL) return NULL;
249 
250   DVPSGraphicAnnotation *annotation = NULL;
251   OFString aString(layer);
252   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
253   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
254   while (first != last)
255   {
256     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame, applicability)))
257     {
258       annotation = *first;
259       first = last;
260     } else ++first;
261   }
262 
263   if (annotation==NULL)
264   {
265     annotation = new DVPSGraphicAnnotation();
266     if (annotation)
267     {
268       annotation->setAnnotationLayer(layer);
269       if (applicability != DVPSB_allImages) annotation->addImageReference(sopclassUID, instanceUID, frame, applicability);
270       list_.push_back(annotation);
271     }
272   }
273 
274   if (annotation)
275   {
276     annotation->addTextObject(text);
277     return text;
278   }
279 
280   delete text;
281   return NULL;
282 }
283 
284 
removeTextObject(const char * layer,const char * instanceUID,unsigned long frame,size_t idx)285 OFCondition DVPSGraphicAnnotation_PList::removeTextObject(const char *layer, const char *instanceUID, unsigned long frame, size_t idx)
286 {
287   if (layer==NULL) return EC_IllegalCall;
288 
289   size_t tmp = 0;
290   OFString aString(layer);
291   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
292   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
293   while (first != last)
294   {
295     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
296     {
297       tmp = (*first)->getNumberOfTextObjects();
298       if (idx < tmp)
299       {
300         DVPSTextObject *textObject = (*first)->removeTextObject(idx);
301         if (textObject)
302         {
303           delete textObject;
304           return EC_Normal;
305         } else return EC_IllegalCall;
306       } else idx -= tmp;
307     }
308     ++first;
309   }
310   return EC_IllegalCall;
311 }
312 
313 
moveTextObject(const char * old_layer,const char * sopclassUID,const char * instanceUID,unsigned long frame,size_t idx,DVPSObjectApplicability applicability,const char * new_layer)314 OFCondition DVPSGraphicAnnotation_PList::moveTextObject(
315     const char *old_layer,
316     const char *sopclassUID,
317     const char *instanceUID,
318     unsigned long frame,
319     size_t idx,
320     DVPSObjectApplicability applicability,
321     const char *new_layer)
322 {
323   if (old_layer==NULL) return EC_IllegalCall;
324   if (new_layer==NULL) return EC_IllegalCall;
325 
326   size_t tmp = 0;
327   OFString aString(old_layer);
328   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
329   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
330   while (first != last)
331   {
332     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
333     {
334       tmp = (*first)->getNumberOfTextObjects();
335       if (idx < tmp)
336       {
337         DVPSTextObject *textObject = (*first)->removeTextObject(idx);
338         if (textObject)
339         {
340           textObject = addTextObject(new_layer, sopclassUID, instanceUID, frame, applicability, textObject);
341           if (textObject) return EC_Normal; else return EC_MemoryExhausted;
342         } else return EC_IllegalCall;
343       } else idx -= tmp;
344     }
345     ++first;
346   }
347   return EC_IllegalCall;
348 }
349 
350 
getNumberOfGraphicObjects(const char * layer,const char * instanceUID,unsigned long frame)351 size_t DVPSGraphicAnnotation_PList::getNumberOfGraphicObjects(const char *layer, const char *instanceUID, unsigned long frame)
352 {
353   if (layer==NULL) return 0;
354 
355   size_t result = 0;
356   OFString aString(layer);
357   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
358   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
359   while (first != last)
360   {
361     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
362     {
363       result += (*first)->getNumberOfGraphicObjects();
364     }
365     ++first;
366   }
367   return result;
368 }
369 
getGraphicObject(const char * layer,const char * instanceUID,unsigned long frame,size_t idx)370 DVPSGraphicObject *DVPSGraphicAnnotation_PList::getGraphicObject(const char *layer, const char *instanceUID, unsigned long frame, size_t idx)
371 {
372   if (layer==NULL) return NULL;
373 
374   size_t tmp = 0;
375   OFString aString(layer);
376   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
377   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
378   while (first != last)
379   {
380     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
381     {
382       tmp = (*first)->getNumberOfGraphicObjects();
383       if (idx < tmp) return (*first)->getGraphicObject(idx); else idx -= tmp;
384     }
385     ++first;
386   }
387   return NULL;
388 }
389 
390 
addGraphicObject(const char * layer,const char * sopclassUID,const char * instanceUID,unsigned long frame,DVPSObjectApplicability applicability,DVPSGraphicObject * graphic)391 DVPSGraphicObject *DVPSGraphicAnnotation_PList::addGraphicObject(
392     const char *layer,
393     const char *sopclassUID,
394     const char *instanceUID,
395     unsigned long frame,
396     DVPSObjectApplicability applicability,
397     DVPSGraphicObject *graphic)
398 {
399   if (layer==NULL) return NULL;
400 
401   if (graphic==NULL) graphic = new DVPSGraphicObject();
402   if (graphic==NULL) return NULL;
403 
404   DVPSGraphicAnnotation *annotation = NULL;
405   OFString aString(layer);
406   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
407   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
408   while (first != last)
409   {
410     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame, applicability)))
411     {
412       annotation = *first;
413       first = last;
414     } else ++first;
415   }
416 
417   if (annotation==NULL)
418   {
419     annotation = new DVPSGraphicAnnotation();
420     if (annotation)
421     {
422       annotation->setAnnotationLayer(layer);
423       if (applicability != DVPSB_allImages) annotation->addImageReference(sopclassUID, instanceUID, frame, applicability);
424       list_.push_back(annotation);
425     }
426   }
427 
428   if (annotation)
429   {
430     annotation->addGraphicObject(graphic);
431     return graphic;
432   }
433 
434   delete graphic;
435   return NULL;
436 }
437 
438 
removeGraphicObject(const char * layer,const char * instanceUID,unsigned long frame,size_t idx)439 OFCondition DVPSGraphicAnnotation_PList::removeGraphicObject(const char *layer, const char *instanceUID, unsigned long frame, size_t idx)
440 {
441   if (layer==NULL) return EC_IllegalCall;
442 
443   size_t tmp = 0;
444   OFString aString(layer);
445   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
446   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
447   while (first != last)
448   {
449     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
450     {
451       tmp = (*first)->getNumberOfGraphicObjects();
452       if (idx < tmp)
453       {
454         DVPSGraphicObject *graphicObject = (*first)->removeGraphicObject(idx);
455         if (graphicObject)
456         {
457           delete graphicObject;
458           return EC_Normal;
459         } else return EC_IllegalCall;
460       } else idx -= tmp;
461     }
462     ++first;
463   }
464   return EC_IllegalCall;
465 }
466 
467 
moveGraphicObject(const char * old_layer,const char * sopclassUID,const char * instanceUID,unsigned long frame,size_t idx,DVPSObjectApplicability applicability,const char * new_layer)468 OFCondition DVPSGraphicAnnotation_PList::moveGraphicObject(
469     const char *old_layer,
470     const char *sopclassUID,
471     const char *instanceUID,
472     unsigned long frame,
473     size_t idx,
474     DVPSObjectApplicability applicability,
475     const char *new_layer)
476 {
477   if (old_layer==NULL) return EC_IllegalCall;
478   if (new_layer==NULL) return EC_IllegalCall;
479 
480   size_t tmp = 0;
481   OFString aString(old_layer);
482   OFListIterator(DVPSGraphicAnnotation *) first = list_.begin();
483   OFListIterator(DVPSGraphicAnnotation *) last = list_.end();
484   while (first != last)
485   {
486     if ((aString == (*first)->getAnnotationLayer()) && ((*first)->isApplicable(instanceUID, frame)))
487     {
488       tmp = (*first)->getNumberOfGraphicObjects();
489       if (idx < tmp)
490       {
491         DVPSGraphicObject *graphicObject = (*first)->removeGraphicObject(idx);
492         if (graphicObject)
493         {
494           graphicObject = addGraphicObject(new_layer, sopclassUID, instanceUID, frame, applicability, graphicObject);
495           if (graphicObject) return EC_Normal; else return EC_MemoryExhausted;
496         } else return EC_IllegalCall;
497       } else idx -= tmp;
498     }
499     ++first;
500   }
501   return EC_IllegalCall;
502 }
503