source: trunk/MagicSoft/Mars/mbase/MParList.cc@ 1350

Last change on this file since 1350 was 1337, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 19.4 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26// //
27// MParList //
28// //
29// This class contains a list of different parameter containers. //
30// //
31// A parameter container is an object which is derived from //
32// MParContainer. //
33// //
34// Normally a parameter container is used for data exchange between two //
35// tasks at runtime. //
36// //
37// You can add every parameter container (Named object) to the //
38// instance and access it from somewhere else via its Name. //
39// //
40/////////////////////////////////////////////////////////////////////////////
41#include "MParList.h"
42
43#include <TNamed.h>
44#include <TClass.h>
45#include <TOrdCollection.h>
46
47#include "MLog.h"
48#include "MLogManip.h"
49
50ClassImp(MParList);
51
52// --------------------------------------------------------------------------
53//
54// default constructor
55// creates an empty list
56//
57MParList::MParList(const char *name, const char *title)
58{
59 fName = name ? name : "MParList";
60 fTitle = title ? title : "A list of Parameter Containers";
61
62 //
63 // This sets a flag that the list is the owner, which means
64 // that the destructor of the list deletes all it's objects
65 //
66 fContainer = new TOrdCollection;
67 fAutodelete = new TOrdCollection;
68}
69
70// --------------------------------------------------------------------------
71//
72// Copy constructor. It copies all entries of the parameter list, but it
73// takes care of, that the automatically created entries are only deleted
74// once. (doesn't copy the list which holds the automatically created
75// entries)
76//
77MParList::MParList(MParList &ts)
78{
79 fContainer->AddAll(ts.fContainer);
80}
81
82// --------------------------------------------------------------------------
83//
84// If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
85// by the destructor
86//
87MParList::~MParList()
88{
89 //
90 // Case:
91 // 1) MParList is owner of the containers:
92 // All container are stored in fContainer, and become deleted by
93 // 'delete fContainer'. Some of these containers, which were
94 // created automatically are stored in fAutodelete, too. To prevent
95 // double deletion this containers are not deleted by the destructor
96 // of fAutodelete.
97 // 2) MParList is not owner of the containers:
98 // The containers which were Added by AddToList are not touched.
99 // Only the containers which were created automatically are also
100 // automatically deleted.
101 //
102 TestBit(kIsOwner) ? fContainer->SetOwner() : fAutodelete->SetOwner();
103
104 delete fContainer;
105 delete fAutodelete;
106}
107
108// --------------------------------------------------------------------------
109//
110// If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
111// by the destructor
112//
113void MParList::SetOwner(Bool_t enable)
114{
115 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
116}
117
118// --------------------------------------------------------------------------
119//
120// Set the logging streamer of the parameter list and all contained
121// parameter containers
122//
123void MParList::SetLogStream(MLog *log)
124{
125 fContainer->ForEach(MParContainer, SetLogStream)(log);
126 MParContainer::SetLogStream(log);
127}
128
129// --------------------------------------------------------------------------
130//
131// Add a single container to the list.
132//
133// If 'where' is given, the object will be added after this.
134//
135Bool_t MParList::AddToList(MParContainer *cont, MParContainer *where)
136{
137 //
138 // check if the object (you want to add) exists
139 //
140
141 if (!cont)
142 return kFALSE;
143
144 //
145 // Get Name of new container
146 //
147 const char *name = cont->GetName();
148
149 //
150 // Check if the new container is already existing in the list
151 //
152 const TObject *objn = fContainer->FindObject(name);
153 const TObject *objt = fContainer->FindObject(cont);
154
155 if (objn || objt)
156 {
157 //
158 // If the container is already in the list ignore it.
159 //
160 if (objt || objn==cont)
161 {
162 *fLog << warn << dbginf << "Warning: Container '" << cont->GetName() << ", 0x" << (void*)cont;
163 *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl;
164 return kTRUE;
165 }
166
167 //
168 // Otherwise add it to the list, but print a warning message
169 //
170 *fLog << warn << dbginf << "Warning: Container with the same name '" << cont->GetName();
171 *fLog << "' already existing in '" << GetName() << "'." << endl;
172 *fLog << "You may not be able to get a pointer to container task by name." << endl;
173 }
174
175 //
176 // check if you want to add the new parameter container somewhere
177 // special (in that case you specify "where")
178 //
179 if (where)
180 {
181 if (!fContainer->FindObject(where))
182 {
183 *fLog << dbginf << "Error: Cannot find parameter container after which the new one should be added!" << endl;
184 return kFALSE;
185 }
186 }
187
188 *fLog << inf << "Adding " << name << " to " << GetName() << "... " << flush;
189
190 fContainer->Add(cont);
191 *fLog << "Done." << endl;
192
193 return kTRUE;
194}
195
196// --------------------------------------------------------------------------
197//
198// Add all entries of the TObjArray to the list.
199//
200void MParList::AddToList(TObjArray *list)
201{
202 //
203 // check if the object (you want to add) exists
204 //
205 if (!list)
206 return;
207
208 TObjArrayIter Next(list);
209
210 MParContainer *cont = NULL;
211 while ((cont=(MParContainer*)Next()))
212 AddToList(cont);
213}
214
215// --------------------------------------------------------------------------
216//
217// Find an object with the same name in the list and replace it with
218// the new one. If the kIsOwner flag is set and the object was not
219// created automatically, the object is deleted.
220//
221Bool_t MParList::Replace(MParContainer *cont)
222{
223 //
224 // check if the object (you want to add) exists
225 //
226 if (!cont)
227 return kFALSE;
228
229 TObject *obj = FindObject(cont->GetName());
230 if (!obj)
231 {
232 *fLog << warn << "No object with the same name '";
233 *fLog << cont->GetName() << "' in list... ignored." << endl;
234 return kFALSE;
235 }
236
237 fContainer->Remove(obj);
238
239 if (TestBit(kIsOwner) && !fAutodelete->FindObject(obj))
240 delete obj;
241
242 *fLog << inf << "MParContainer '" << obj->GetName() << "' found and replaced..." << endl;
243
244 return AddToList(cont);
245}
246
247// --------------------------------------------------------------------------
248//
249// Find an object in the list.
250// 'name' is the name of the object you are searching for.
251//
252TObject *MParList::FindObject(const char *name) const
253{
254 return fContainer->FindObject(name);
255}
256
257// --------------------------------------------------------------------------
258//
259// check if the object is in the list or not
260//
261TObject *MParList::FindObject(const TObject *obj) const
262{
263 return fContainer->FindObject(obj);
264}
265
266// --------------------------------------------------------------------------
267//
268// Find an object in the list and check for the correct inheritance.
269// 'name' is the name of the object you are searching for.
270//
271TObject *MParList::FindObject(const char *name, const char *classname) const
272{
273 TObject *obj = fContainer->FindObject(name);
274
275 if (!obj)
276 return NULL;
277
278 if (obj->InheritsFrom(classname))
279 return obj;
280
281 *fLog << dbginf << warn << "Found object '" << name << "' doesn't ";
282 *fLog << "inherit from " << "'" << classname << "'" << endl;
283 return NULL;
284}
285
286// --------------------------------------------------------------------------
287//
288// check if the object is in the list or not and check for the correct
289// inheritance
290//
291TObject *MParList::FindObject(const TObject *obj, const char *classname) const
292{
293 TObject *nobj = fContainer->FindObject(obj);
294
295 if (!nobj)
296 return NULL;
297
298 if (nobj->InheritsFrom(classname))
299 return nobj;
300
301 *fLog << dbginf << warn << "Found object '" << nobj->GetName() << "' ";
302 *fLog << "doesn't inherit from " << "'" << classname << "'" << endl;
303 return NULL;
304}
305
306// --------------------------------------------------------------------------
307//
308// returns the ClassName without anything which is behind that last ';' in
309// string.
310//
311TString MParList::GetClassName(const char *classname)
312{
313 TString cname(classname);
314 const char *semicolon = strrchr(cname, ';');
315
316 if (semicolon)
317 cname.Remove(semicolon-cname);
318
319 return cname;
320}
321
322// --------------------------------------------------------------------------
323//
324// returns the ObjectName. It is created from a class and object name.
325// If no object name is given the objectname is the same than the
326// class name. Leading dots are removed from the object name
327//
328TString MParList::GetObjectName(const char *classname, const char *objname)
329{
330 TString cname(classname);
331 const char *semicolon = strrchr(cname, ';');
332
333 TString oname(objname ? objname : classname);
334
335 if (semicolon)
336 {
337 //
338 // Remove leading dots from objectname (eg. "MMcTrig;5.")
339 //
340 Int_t sz = oname.Sizeof()-2;
341
342 while (sz>=0 && oname[sz]=='.')
343 oname.Remove(sz--);
344 }
345 return oname;
346}
347
348// --------------------------------------------------------------------------
349//
350// Find an object in the list.
351// 'name' is the name of the object you are searching for.
352// If the object doesn't exist we try to create one from the
353// dictionary. If this isn't possible NULL is returned.
354//
355// An object which was created automatically is deleted automatically in
356// the destructor of the parameter list, too. This means, that if an
357// object should survive (eg. Histograms) you MUST create it by yourself
358// and add it to the parameter list.
359//
360// By default (you don't specify an object name) the object name is
361// the same as the classname
362//
363// If the classname (default classname) is of the structure
364// "Name;something" - containing a semicolon - evarything which is
365// after the last appearance of a semicolon is stripped to get the
366// Name of the Class. Normally this is used to number your objects.
367// "Name;1", "Name;2", ... If a semicolon is detected leading dots
368// are stripped from the object-name (eg. "name;5.")
369//
370MParContainer *MParList::FindCreateObj(const char *classname, const char *objname)
371{
372 //
373 // If now object name (name of the object to identify it in the
374 // List) is given use it's classname as the objectname
375 //
376
377 //
378 // Check if the classname is a 'numbered' name (like: "MTime;2")
379 // if so strip the number from the classname.
380 //
381 // Becareful: We check for the last occurance of a ';' only and we
382 // also don't check if a number follows or something else.
383 //
384 // Rem: I use a TString to make the code more readyble and to get
385 // the new object deleted automatically
386 //
387 TString cname = GetClassName(classname);
388 TString oname = GetObjectName(classname, objname);
389
390 //
391 // Try to find a object with this object name which is already
392 // in the List. If we can find one we are done.
393 //
394 MParContainer *pcont = (MParContainer*)FindObject(oname);
395
396 if (pcont)
397 {
398 if (pcont->InheritsFrom(cname))
399 return pcont;
400
401 *fLog << err << "Warning: Object '" << oname << "' found in list doesn't inherit from " << cname << "." << endl;
402 return NULL;
403 }
404
405 //
406 // if object is not existing in the list try to create one
407 //
408 *fLog << inf << "Object '" << oname << "' [" << cname << "] not yet in " << GetName() << "... creating." << endl;
409
410 //
411 // try to get class from root environment
412 //
413 TClass *cls = gROOT->GetClass(cname);
414 if (!cls)
415 {
416 //
417 // if class is not existing in the root environment
418 //
419 *fLog << err << dbginf << "Class '" << cname << "' not existing in dictionary." << endl;
420 return NULL;
421 }
422
423 //
424 // create the parameter container of the the given class type
425 //
426 pcont = (MParContainer*)cls->New();
427 if (!pcont)
428 {
429 *fLog << err << dbginf << "Cannot create new instance of class '" << cname << "' (Maybe no def. constructor)" << endl;
430 return NULL;
431 }
432
433 //
434 // Set the name of the container
435 //
436 pcont->SetName(oname);
437
438 //
439 // Now add the object to the parameter list
440 //
441 AddToList(pcont);
442
443 //
444 // The object was automatically created. This makes sure, that such an
445 // object is deleted together with the list
446 //
447 fAutodelete->Add(pcont);
448
449 //
450 // Find an object in the list.
451 // 'name' is the name of the object you are searching for.
452 //
453 return pcont;
454}
455
456// --------------------------------------------------------------------------
457//
458// print some information about the current status of MParList
459//
460void MParList::Print(Option_t *t) const
461{
462 *fLog << all << " " << GetDescriptor() << endl;
463 *fLog << setfill('-') << setw(strlen(GetDescriptor())+2) << "" << endl;
464 MParContainer *obj = NULL;
465 TIter Next(fContainer);
466 while ((obj=(MParContainer*)Next()))
467 *fLog << " " << obj->GetDescriptor() << endl;
468 *fLog << endl;
469}
470
471// --------------------------------------------------------------------------
472//
473// Sets the flags off all containers in the list (and the list
474// itself) to unchanged
475//
476void MParList::SetReadyToSave(Bool_t flag)
477{
478 fContainer->ForEach(MParContainer, SetReadyToSave)(flag);
479 MParContainer::SetReadyToSave(flag);
480}
481
482// --------------------------------------------------------------------------
483//
484// Reset all containers in the list
485//
486void MParList::Reset()
487{
488 fContainer->ForEach(MParContainer, Reset)();
489}
490
491// --------------------------------------------------------------------------
492//
493// This finds numbered objects. The objects are returned in a copy of a
494// TObjArray.
495//
496// If from only is given (or to=0) object are assumed numbered
497// from 1 to from.
498//
499TObjArray MParList::FindObjectList(const char *name, UInt_t first, const UInt_t last) const
500{
501 TObjArray list;
502
503 if (first>0 && last<first)
504 {
505 *fLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
506 return list;
507 }
508
509 const UInt_t len = strlen(name);
510
511 char *auxname = new char[len+7];
512 strcpy(auxname, name);
513
514 if (first==0 && last!=0)
515 first = 1;
516
517 //
518 // If only 'from' is specified the number of entries are ment
519 //
520 for (UInt_t i=first; i<=last; i++)
521 {
522 if (first!=0 || last!=0)
523 sprintf(auxname+len, ";%d", i);
524
525 TObject *obj = FindObject(auxname);
526 if (!obj)
527 continue;
528
529 list.AddLast(obj);
530 }
531 delete auxname;
532
533 return list;
534}
535
536// --------------------------------------------------------------------------
537//
538// This finds numbered objects. The objects are returned in a copy of a
539// TObjArray. If one of the objects doesn't exist it is created from the
540// meaning of cname and oname (s. FindCreateObj)
541//
542// If from only is given (or to=0) object are assumed numbered
543// from 1 to from.
544//
545TObjArray MParList::FindCreateObjList(const char *cname, UInt_t first, const UInt_t last, const char *oname)
546{
547 TObjArray list;
548
549 if (first>0 && last<first)
550 {
551 *fLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
552 return list;
553 }
554
555 const UInt_t len = strlen(cname);
556
557 char *auxname = new char[len+7];
558 strcpy(auxname, cname);
559
560 //
561 // If only 'from' is specified the number of entries are ment
562 //
563 if (first==0 && last!=0)
564 first = 1;
565
566 for (UInt_t i=first; i<=last; i++)
567 {
568 if (first!=0 || last!=0)
569 sprintf(auxname+len, ";%d", i);
570
571 TObject *obj = FindCreateObj(auxname, oname);
572 if (!obj)
573 break;
574
575 list.AddLast(obj);
576 }
577 delete auxname;
578
579 return list;
580}
581
582// --------------------------------------------------------------------------
583//
584// This finds numbered objects. The objects are returned in a copy of a
585// TObjArray. If one of the objects doesn't exist it is created from the
586// meaning of cname and oname (s. FindCreateObj)
587//
588// If from only is given (or to=0) object are assumed numbered
589// from 1 to from.
590//
591// Remark: Because it is static the object are only created and not added to
592// the parameter list. You must also take care of deleting these objects!
593// This function is mainly made for use in root macros. Don't use it in
594// compiled programs if you are not 100% sure what you are doing.
595//
596TObjArray MParList::CreateObjList(const char *cname, UInt_t first, const UInt_t last, const char *oname)
597{
598 TObjArray list;
599
600 if (first>0 && last<first)
601 {
602 gLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
603 return list;
604 }
605
606 //
607 // try to get class from root environment
608 //
609 TClass *cls = gROOT->GetClass(cname);
610 if (!cls)
611 {
612 //
613 // if class is not existing in the root environment
614 //
615 gLog << dbginf << "Class '" << cname << "' not existing in dictionary." << endl;
616 return list;
617 }
618
619 const UInt_t len = strlen(cname);
620
621 char *auxname = new char[len+7];
622 strcpy(auxname, cname);
623
624 //
625 // If only 'from' is specified the number of entries are ment
626 //
627 if (first==0 && last!=0)
628 first = 1;
629
630 for (UInt_t i=first; i<=last; i++)
631 {
632 if (first!=0 || last!=0)
633 sprintf(auxname+len, ";%d", i);
634
635 //
636 // create the parameter container of the the given class type
637 //
638 MParContainer *pcont = (MParContainer*)cls->New();
639 if (!pcont)
640 {
641 gLog << err << dbginf << "Cannot create new instance of class '" << cname << "' (Maybe no def. constructor)" << endl;
642 return list;
643 }
644
645 //
646 // Set the name of the container
647 //
648 pcont->SetName(auxname);
649
650 //
651 // Add new object to the return list
652 //
653 list.AddLast(pcont);
654 }
655 delete auxname;
656
657 return list;
658}
Note: See TracBrowser for help on using the repository browser.