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

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