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

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