source: trunk/Mars/mbase/MParList.cc

Last change on this file was 19345, checked in by tbretz, 20 months ago
Improves the behaviour with RecursiveRemove. Strictly speaking this change might only be necessary if a class contains more than one member which is bound to recursive remove. Onth other hand setting all members to NULL which might be affected by RecursiveRemove is not wrong either.
File size: 29.2 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>     // 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
52#include "MIter.h"
53#include "MParEnv.h"
54#include "MTaskList.h"
55
56ClassImp(MParList);
57
58using namespace std;
59
60static const TString gsDefName  = "MParList";
61static const TString gsDefTitle = "A list of Parameter Containers";
62
63// --------------------------------------------------------------------------
64//
65//  creates an empty list
66//
67void MParList::Init(const char *name, const char *title)
68{
69    fName  = name  ? name  : gsDefName.Data();
70    fTitle = title ? title : gsDefTitle.Data();
71
72    //
73    // This sets a flag that the list is the owner, which means
74    // that the destructor of the list deletes all it's objects
75    //
76    fContainer  = new TOrdCollection;
77    fAutodelete = new TOrdCollection;
78
79    gROOT->GetListOfCleanups()->Add(fContainer);
80    gROOT->GetListOfCleanups()->Add(fAutodelete);
81    fContainer->SetBit(kMustCleanup);
82    fAutodelete->SetBit(kMustCleanup);
83}
84
85
86// --------------------------------------------------------------------------
87//
88//  default constructor
89//  creates an empty list
90//
91MParList::MParList(const char *name, const char *title)
92{
93    Init(name, title);
94}
95
96// --------------------------------------------------------------------------
97//
98//  Copy constructor. It copies all entries of the parameter list, but it
99//  takes care of, that the automatically created entries are only deleted
100//  once. (doesn't copy the list which holds the automatically created
101//  entries)
102//
103MParList::MParList(const MParList &ts, const char *name, const char *title) : MParContainer()
104{
105    Init(name, title);
106
107    fContainer->AddAll(ts.fContainer);
108}
109
110// --------------------------------------------------------------------------
111//
112//  If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
113//  by the destructor
114//
115MParList::~MParList()
116{
117    //
118    // Case:
119    //  1) MParList is owner of the containers:
120    //     All container are stored in fContainer, and become deleted by
121    //     'delete fContainer'. Some of these containers, which were
122    //     created automatically are stored in fAutodelete, too. To prevent
123    //     double deletion this containers are not deleted by the destructor
124    //     of fAutodelete.
125    //  2) MParList is not owner of the containers:
126    //     The containers which were Added by AddToList are not touched.
127    //     Only the containers which were created automatically are also
128    //     automatically deleted.
129    //
130    IsOwner() ? fContainer->SetOwner() : fAutodelete->SetOwner();
131
132    TIter Next(fContainer);
133    TObject *o=0;
134    while ((o=Next()))
135        if (o->TestBit(kCanDelete))
136            delete fContainer->Remove(o);
137
138    // FIXME? If fContainer is owner do we have to remove the object
139    //   from fAutodelete due to the access when checking for a
140    //   garbage collection?
141    delete fContainer;
142    fContainer = 0;
143
144    delete fAutodelete;
145    fAutodelete = 0;
146
147}
148
149// --------------------------------------------------------------------------
150//
151//  If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
152//  by the destructor
153//
154void MParList::SetOwner(Bool_t enable)
155{
156    enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
157}
158
159// --------------------------------------------------------------------------
160//
161//  Set the logging streamer of the parameter list and all contained
162//  parameter containers
163//
164void MParList::SetLogStream(MLog *log)
165{
166    fContainer->R__FOR_EACH(MParContainer, SetLogStream)(log);
167    MParContainer::SetLogStream(log);
168}
169
170void MParList::SetDisplay(MStatusDisplay *d)
171{
172    fContainer->R__FOR_EACH(MParContainer, SetDisplay)(d);
173    MParContainer::SetDisplay(d);
174}
175
176// --------------------------------------------------------------------------
177//
178//  Add a single container to the list.
179//
180//  If 'where' is given, the object will be added after this.
181//
182Bool_t MParList::AddToList(MParContainer *cont, MParContainer *where)
183{
184    //
185    //  check if the object (you want to add) exists
186    //
187    if (!cont)
188        return kFALSE;
189
190    if (cont==this)
191    {
192        *fLog << err << dbginf << "Error: It is not allowed to add a parameter list to itself." << endl;
193        return kFALSE;
194    }
195
196    //
197    // Get Name of new container
198    //
199    const char *name = cont->GetName();
200
201    //
202    // Check if the new container is already existing in the list
203    //
204    const TObject *objn = fContainer->FindObject(name);
205    const TObject *objt = fContainer->FindObject(cont);
206
207    if (objn || objt)
208    {
209        //
210        // If the container is already in the list ignore it.
211        //
212        if (objt || objn==cont)
213        {
214            *fLog << warn << dbginf << "Warning: Container '" << cont->GetName() << ", 0x" << (void*)cont;
215            *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl;
216            return kTRUE;
217        }
218
219        //
220        // Otherwise add it to the list, but print a warning message
221        //
222        *fLog << warn << dbginf << "Warning: Container with the same name '" << cont->GetName();
223        *fLog << "' already existing in '" << GetName() << "'." << endl;
224        *fLog << "You may not be able to get a pointer to container task by name." << endl;
225    }
226
227    //
228    //  check if you want to add the new parameter container somewhere
229    //  special (in that case you specify "where")
230    //
231    if (where)
232    {
233        if (!fContainer->FindObject(where))
234        {
235            *fLog << err << dbginf << "Error: Cannot find parameter container after which the new one should be added!" << endl;
236            return kFALSE;
237        }
238    }
239
240    if (!cont->InheritsFrom(MParContainer::Class()))
241    {
242        *fLog << err << dbginf << "Error: Cantainer MUST derive from MParContainer!" << endl;
243        return kFALSE;
244    }
245
246    *fLog << inf3 << "Adding " << name << " to " << GetName() << "... " << flush;
247
248    cont->SetBit(kMustCleanup);
249    fContainer->Add(cont);
250    *fLog << "done." << endl;
251
252    return kTRUE;
253}
254
255// --------------------------------------------------------------------------
256//
257// Add all entries which derive from MParContainer
258// of the TObjArray to the list.
259//
260void MParList::AddToList(TObjArray *list)
261{
262    //
263    //  check if the object (you want to add) exists
264    //
265    if (!list)
266        return;
267
268    TIter Next(list);
269
270    TObject *cont = NULL;
271    while ((cont=Next()))
272    {
273        MParContainer *par = dynamic_cast<MParContainer*>(cont);
274        if (par)
275            AddToList(par);
276    }
277}
278
279// --------------------------------------------------------------------------
280//
281//  Find an object with the same name in the list and replace it with
282//  the new one. If the kIsOwner flag is set and the object was not
283//  created automatically, the object is deleted.
284//
285Bool_t MParList::Replace(MParContainer *cont)
286{
287    //
288    //  check if the object (you want to add) exists
289    //
290    if (!cont)
291        return kFALSE;
292
293    TObject *obj = FindObject(cont->GetName());
294    if (!obj)
295    {
296        *fLog << warn << "No object with the same name '";
297        *fLog << cont->GetName() << "' in list... adding." << endl;
298        return AddToList(cont);
299    }
300
301    fContainer->Remove(obj);
302
303    if (IsOwner() && !fAutodelete->FindObject(obj))
304        delete obj;
305
306    *fLog << inf2 << "MParContainer '" << cont->GetName() << "' found and replaced..." << endl;
307
308    return AddToList(cont);
309}
310
311// --------------------------------------------------------------------------
312//
313//  Find an object with the same name in the list and remove it.
314//  If the kIsOwner flag is set and the object was not created
315//  automatically, the object is deleted.
316//
317void MParList::Remove(MParContainer *cont)
318{
319    //
320    //  check if the object (you want to add) exists
321    //
322    if (!cont)
323        return;
324
325    TObject *obj = fContainer->Remove(cont);
326
327    fContainer->RecursiveRemove(obj);
328
329    // if (!obj)
330    // {
331        //        *fLog << warn << "Object not found in list..." << endl;
332    //    return;
333    //}
334
335//    *fLog << inf << "MParContainer '" << cont->GetName() << "' removed..." << endl;
336
337    if (obj && IsOwner() && !fAutodelete->FindObject(obj))
338        delete obj;
339}
340
341// --------------------------------------------------------------------------
342//
343// Call MParContainer::RecursiveRemove
344// Call fContainer->RecursiveRemove
345//
346void MParList::RecursiveRemove(TObject *obj)
347{
348    MParContainer::RecursiveRemove(obj);
349
350    if (obj==fContainer)
351        fContainer = NULL;
352
353    if (fContainer)
354        fContainer->RecursiveRemove(obj);
355}
356
357// --------------------------------------------------------------------------
358//
359//  Find an object in the list.
360//  'name' is the name of the object you are searching for.
361//
362TObject *MParList::FindObject(const char *name) const
363{
364    TObject *obj = fContainer->FindObject(name);
365    const MParEnv *env = dynamic_cast<const MParEnv*>(obj);
366    return env ? env->GetCont() : obj;
367}
368
369// --------------------------------------------------------------------------
370//
371//  check if the object is in the list or not
372//
373TObject *MParList::FindObject(const TObject *obj) const
374{
375    TObject *ret = fContainer->FindObject(obj);
376    const MParEnv *env = dynamic_cast<const MParEnv*>(ret);
377    return env ? env->GetCont() : ret;
378}
379
380// --------------------------------------------------------------------------
381//
382//  Find an object in the list and check for the correct inheritance.
383//  'name' is the name of the object you are searching for.
384//
385// In words: Find object name and check whether it inherits from classname
386//
387TObject *MParList::FindObject(const char *name, const char *classname) const
388{
389    TObject *obj = FindObject(name);
390
391    if (!obj)
392        return NULL;
393
394    if (obj->InheritsFrom(classname))
395        return obj;
396
397    *fLog << dbginf << warn << "Found object '" << name << "' doesn't ";
398    *fLog << "inherit from " << "'" << classname << "' but from '";
399    *fLog << obj->ClassName() << "'" << endl;
400    return NULL;
401}
402
403// --------------------------------------------------------------------------
404//
405//  check if the object is in the list or not and check for the correct
406//  inheritance
407//
408TObject *MParList::FindObject(const TObject *obj, const char *classname) const
409{
410    TObject *nobj = FindObject(obj);
411
412    if (!nobj)
413        return NULL;
414
415    if (nobj->InheritsFrom(classname))
416        return nobj;
417
418    *fLog << dbginf << warn << "Found object '" << nobj->GetName() << "' ";
419    *fLog << "doesn't inherit from " << "'" << classname << "'" << endl;
420    return NULL;
421}
422
423// --------------------------------------------------------------------------
424//
425//  Searches for the tasklist tlist (default: MTaskList) and returns
426//  a task with the given name found in this list. If one of both isn't
427//  found NULL is returned
428//
429MTask *MParList::FindTask(const char *name, const char *tlist) const
430{
431    TObject *l = FindObject(tlist, "MTaskList");
432    return (MTask*)(l ? l->FindObject(name) : NULL);
433}
434
435// --------------------------------------------------------------------------
436//
437//  Find a tasklist which contains a task with name name
438//
439MTaskList *MParList::FindTaskListWithTask(const char *name) const
440{
441    TIter Next(fContainer);
442    TObject *o=0;
443    while ((o=Next()))
444    {
445        MTaskList *l1 = dynamic_cast<MTaskList*>(o);
446        if (!l1)
447            continue;
448
449        MTaskList *l2 = l1->FindTaskList(name);
450        if (l2)
451            return l2;
452    }
453    return 0;
454}
455
456// --------------------------------------------------------------------------
457//
458//  Find a tasklist which contains a task task
459//
460MTaskList *MParList::FindTaskListWithTask(const MTask *task) const
461{
462    TIter Next(fContainer);
463    TObject *o=0;
464    while ((o=Next()))
465    {
466        MTaskList *l1 = dynamic_cast<MTaskList*>(o);
467        if (!l1)
468            continue;
469
470        MTaskList *l2 = l1->FindTaskList(task);
471        if (l2)
472            return l2;
473    }
474    return 0;
475}
476
477// --------------------------------------------------------------------------
478//
479//  returns the ClassName without anything which is behind that last ';' in
480//  string.
481//
482TString MParList::GetClassName(const char *classname)
483{
484    TString cname(classname);
485    const char *semicolon = strrchr(cname, ';');
486
487    if (semicolon)
488        cname.Remove(semicolon-cname);
489
490    return cname;
491}
492
493// --------------------------------------------------------------------------
494//
495//  returns the ObjectName. It is created from a class and object name.
496//  If no object name is given the objectname is the same than the
497//  class name. Leading dots are removed from the object name
498//
499TString MParList::GetObjectName(const char *classname, const char *objname)
500{
501    TString cname(classname);
502    const char *semicolon = strrchr(cname, ';');
503
504    TString oname(objname ? objname : classname);
505
506    if (semicolon)
507    {
508        //
509        // Remove leading dots from objectname (eg. "MMcTrig;5.")
510        //
511        Int_t sz = oname.Sizeof()-2;
512
513        while (sz>=0 && oname[sz]=='.')
514            oname.Remove(sz--);
515    }
516    return oname;
517}
518
519// --------------------------------------------------------------------------
520//
521//  Find an object in the list.
522//  'name' is the name of the object you are searching for.
523//  If the object doesn't exist we try to create one from the
524//  dictionary. If this isn't possible NULL is returned.
525//
526//  An object which was created automatically is deleted automatically in
527//  the destructor of the parameter list, too. This means, that if an
528//  object should survive (eg. Histograms) you MUST create it by yourself
529//  and add it to the parameter list.
530//
531//  By default (you don't specify an object name) the object name is
532//  the same as the classname
533//
534//  If the classname (default classname) is of the structure
535//  "Name;something" - containing a semicolon - evarything which is
536//  after the last appearance of a semicolon is stripped to get the
537//  Name of the Class. Normally this is used to number your objects.
538//  "Name;1", "Name;2", ... If a semicolon is detected leading dots
539//  are stripped from the object-name (eg. "name;5.")
540//
541// In words: Create object of type classname and set its name to objname.
542//           If an object with objname already exists return it.
543//
544MParContainer *MParList::FindCreateObj(const char *classname, const char *objname)
545{
546    //
547    // If now object name (name of the object to identify it in the
548    // List) is given use it's classname as the objectname
549    //
550
551    //
552    // Check if the classname is a 'numbered' name (like: "MTime;2")
553    // if so strip the number from the classname.
554    //
555    // Becareful: We check for the last occurance of a ';' only and we
556    // also don't check if a number follows or something else.
557    //
558    // Rem: I use a TString to make the code more readyble and to get
559    // the new object deleted automatically
560    //
561    TString cname = GetClassName(classname);
562    TString oname = GetObjectName(classname, objname);
563
564    //
565    // Try to find a object with this object name which is already
566    // in the List. If we can find one we are done.
567    //
568    MParContainer *pcont = (MParContainer*)FindObject(oname);
569
570    if (pcont)
571    {
572        if (pcont->InheritsFrom(cname))
573            return pcont;
574
575        *fLog << err << "Warning: Object '" << oname << "' found in list doesn't inherit from " << cname << "." << endl;
576        return NULL;
577    }
578
579    //
580    // if object is not existing in the list try to create one
581    //
582    *fLog << inf2 << "Object '" << oname << "' ";
583    if (oname!=cname)
584        *fLog << "[" << cname << "] ";
585    *fLog << "not yet in " << GetName() << "... creating." << endl;
586
587    //
588    // try to get class from root environment
589    //
590    *fLog << err;
591    TClass *cls = GetClass(cname, fLog);
592    if (!cls)
593        return NULL;
594
595    if (!cls->InheritsFrom(MParContainer::Class()))
596    {
597        *fLog << err << dbginf << "Cannot create new instance of class '" << cname << "': " << endl;
598        *fLog << "Class doesn't inherit from MParContainer." << endl;
599        return NULL;
600    }
601
602    //
603    // create the parameter container of the the given class type
604    //
605    pcont = (MParContainer*)cls->New();
606    if (!pcont)
607    {
608        *fLog << err << dbginf << "Cannot create new instance of class '" << cname << "': " << endl;
609        *fLog << " - Class has no default constructor." << endl;
610        *fLog << " - An abstract member functions of a base class is not overwritten." << endl;
611        return NULL;
612    }
613
614    //
615    // Set the name of the container
616    //
617    pcont->SetName(oname);
618
619    //
620    // Now add the object to the parameter list
621    //
622    AddToList(pcont);
623
624    //
625    // The object was automatically created. This makes sure, that such an
626    // object is deleted together with the list
627    //
628    fAutodelete->Add(pcont);
629
630    //
631    //  Find an object in the list.
632    //  'name' is the name of the object you are searching for.
633    //
634    return pcont;
635}
636
637// --------------------------------------------------------------------------
638//
639//   print some information about the current status of MParList
640//
641void MParList::Print(Option_t *) const
642{
643    *fLog << all << underline << GetDescriptor() << ":" << endl;
644
645    MParContainer *obj = NULL;
646    MIter Next(fContainer);
647    while ((obj=Next()))
648    {
649        *fLog << " " << obj->GetDescriptor();
650        if (fAutodelete->FindObject(obj))
651            *fLog << " <autodel>";
652        *fLog << endl;
653    }
654    *fLog << endl;
655}
656
657// --------------------------------------------------------------------------
658//
659//   Sets the flags off all containers in the list (and the list
660//   itself) to unchanged
661//
662void MParList::SetReadyToSave(Bool_t flag)
663{
664    fContainer->R__FOR_EACH(MParContainer, SetReadyToSave)(flag);
665    MParContainer::SetReadyToSave(flag);
666}
667
668// --------------------------------------------------------------------------
669//
670//   Reset all containers in the list
671//
672void MParList::Reset()
673{
674    fContainer->R__FOR_EACH(MParContainer, Reset)();
675}
676
677// --------------------------------------------------------------------------
678//
679//  This finds numbered objects. The objects are returned in a copy of a
680//  TObjArray.
681//
682//  If from only is given (or to=0) object are assumed numbered
683//  from 1 to from.
684//
685TObjArray MParList::FindObjectList(const char *name, UInt_t first, const UInt_t last) const
686{
687    TObjArray list;
688
689    if (first>0 && last<first)
690    {
691        *fLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
692        return list;
693    }
694
695    const UInt_t len = strlen(name);
696
697    char *auxname = new char[len+7];
698    strcpy(auxname, name);
699
700    if (first==0 && last!=0)
701        first = 1;
702
703    //
704    // If only 'from' is specified the number of entries are ment
705    //
706    for (UInt_t i=first; i<=last; i++)
707    {
708        if (first!=0 || last!=0)
709            sprintf(auxname+len, ";%d", i);
710
711        TObject *obj = FindObject(auxname);
712        if (!obj)
713            continue;
714
715        list.AddLast(obj);
716    }
717    delete [] auxname;
718
719    return list;
720}
721
722// --------------------------------------------------------------------------
723//
724//  This finds numbered objects. The objects are returned in a copy of a
725//  TObjArray. If one of the objects doesn't exist it is created from the
726//  meaning of cname and oname (s. FindCreateObj)
727//
728//  If from only is given (or to=0) object are assumed numbered
729//  from 1 to from.
730//
731TObjArray MParList::FindCreateObjList(const char *cname, UInt_t first, const UInt_t last, const char *oname)
732{
733    TObjArray list;
734
735    if (first>0 && last<first)
736    {
737        *fLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
738        return list;
739    }
740
741    const UInt_t len = strlen(cname);
742
743    char *auxname = new char[len+7];
744    strcpy(auxname, cname);
745
746    //
747    // If only 'from' is specified the number of entries are ment
748    //
749    if (first==0 && last!=0)
750        first = 1;
751
752    for (UInt_t i=first; i<=last; i++)
753    {
754        if (first!=0 || last!=0)
755            sprintf(auxname+len, ";%d", i);
756
757        TObject *obj = FindCreateObj(auxname, oname);
758        if (!obj)
759            break;
760
761        list.AddLast(obj);
762    }
763    delete [] auxname;
764
765    return list;
766}
767
768// --------------------------------------------------------------------------
769//
770//  This finds numbered objects. The objects are returned in a copy of a
771//  TObjArray. If one of the objects doesn't exist it is created from the
772//  meaning of cname and oname (s. FindCreateObj)
773//
774//  If from only is given (or to=0) object are assumed numbered
775//  from 1 to from.
776//
777//  Remark: Because it is static the object are only created and not added to
778//  the parameter list. You must also take care of deleting these objects!
779//  This function is mainly made for use in root macros. Don't use it in
780//  compiled programs if you are not 100% sure what you are doing.
781//
782TObjArray MParList::CreateObjList(const char *cname, UInt_t first, const UInt_t last, const char *)
783{
784    TObjArray list;
785
786    if (first>0 && last<first)
787    {
788        gLog << err << dbginf << "Cannot create entries backwards (last<first)...skipped." << endl;
789        return list;
790    }
791
792    //
793    // try to get class from root environment
794    //
795    gLog << err;
796    TClass *cls = GetClass(cname, &gLog);
797    if (!cls)
798        return list;
799
800    if (!cls->InheritsFrom(MParContainer::Class()))
801    {
802        gLog << err << dbginf << "Cannot create new instance of class '" << cname << "': " << endl;
803        gLog << "Class doesn't inherit from MParContainer." << endl;
804        return list;
805    }
806
807    const UInt_t len = strlen(cname);
808
809    char *auxname = new char[len+7];
810    strcpy(auxname, cname);
811
812    //
813    // If only 'from' is specified the number of entries are ment
814    //
815    if (first==0 && last!=0)
816        first = 1;
817
818    for (UInt_t i=first; i<=last; i++)
819    {
820        if (first!=0 || last!=0)
821            sprintf(auxname+len, ";%d", i);
822
823        //
824        // create the parameter container of the the given class type
825        //
826        MParContainer *pcont = (MParContainer*)cls->New();
827        if (!pcont)
828        {
829            gLog << err << dbginf << "Cannot create new instance of class '" << cname << "' (Maybe no def. constructor)" << endl;
830            return list;
831        }
832
833        //
834        // Set the name of the container
835        //
836        pcont->SetName(auxname);
837
838        //
839        // Add new object to the return list
840        //
841        list.AddLast(pcont);
842    }
843    delete [] auxname;
844
845    return list;
846}
847
848void MParList::SavePrimitive(ostream &out, Option_t *)
849{
850    Bool_t saved = IsSavedAsPrimitive();
851
852    MParContainer::SavePrimitive(out);
853
854    MIter Next(fContainer);
855
856    MParContainer *cont = NULL;
857    while ((cont=Next()))
858    {
859        //
860        // Because it was automatically created don't store its primitive
861        // I guess it will be automatically created again
862        //
863        if (fAutodelete->FindObject(cont) || cont->IsSavedAsPrimitive())
864            continue;
865
866        cont->SavePrimitive(out, "");
867
868        out << "   " << GetUniqueName() << ".";
869        out << (cont->InheritsFrom("MTaskList") && saved ? "Replace" : "AddToList");
870        out << "(&" << cont->GetUniqueName() << ");" << endl << endl;
871    }
872}
873
874void MParList::SavePrimitive(ofstream &out, Option_t *o)
875{
876    SavePrimitive(static_cast<ostream&>(out), o);
877}
878
879// --------------------------------------------------------------------------
880//
881// Implementation of SavePrimitive. Used to write the call to a constructor
882// to a macro. In the original root implementation it is used to write
883// gui elements to a macro-file.
884//
885void MParList::StreamPrimitive(ostream &out) const
886{
887    out << "   MParList " << GetUniqueName();
888    if (fName!=gsDefName || fTitle!=gsDefTitle)
889    {
890        out << "(\"" << fName << "\"";
891        if (fTitle!=gsDefTitle)
892            out << ", \"" << fTitle << "\"";
893        out <<")";
894    }
895    out << ";" << endl << endl;
896}
897
898// --------------------------------------------------------------------------
899//
900// Adds one TNamed object per object in the list. The TNamed object must
901// be deleted by the user.
902//
903void MParList::GetNames(TObjArray &arr) const
904{
905    MParContainer::GetNames(arr);
906    fContainer->R__FOR_EACH(MParContainer, GetNames)(arr);
907}
908
909// --------------------------------------------------------------------------
910//
911// Sets name and title of each object in the list from the objects in
912// the array.
913//
914void MParList::SetNames(TObjArray &arr)
915{
916    MParContainer::SetNames(arr);
917    fContainer->R__FOR_EACH(MParContainer, SetNames)(arr);
918}
919
920// --------------------------------------------------------------------------
921//
922// Read the contents/setup of a parameter container/task from a TEnv
923// instance (steering card/setup file).
924// The key to search for in the file should be of the syntax:
925//    prefix.vname
926// While vname is a name which is specific for a single setup date
927// (variable) of this container and prefix is something like:
928//    evtloopname.name
929// While name is the name of the containers/tasks in the parlist/tasklist
930//
931// eg.  Job4.MImgCleanStd.CleaningLevel1:  3.0
932//      Job4.MImgCleanStd.CleaningLevel2:  2.5
933//
934// If this cannot be found the next step is to search for
935//      MImgCleanStd.CleaningLevel1:  3.0
936// And if this doesn't exist, too, we search for:
937//      CleaningLevel1:  3.0
938//
939// Warning: The programmer is responsible for the names to be unique in
940//          all Mars classes.
941//
942Int_t MParList::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
943{
944    if (print)
945        *fLog << all << "MParList::ReadEnv: " << prefix << endl;
946
947    MParContainer *cont = NULL;
948
949    MIter Next(fContainer);
950    while ((cont=Next()))
951    {
952        if (cont->InheritsFrom("MTaskList"))
953        {
954            if (cont->ReadEnv(env, prefix, print)==kERROR)
955                return kERROR;
956            continue;
957        }
958
959        if (cont->TestEnv(env, prefix, print)==kERROR)
960            return kERROR;
961    }
962
963    return kTRUE;
964}
965
966// --------------------------------------------------------------------------
967//
968// Write the contents/setup of a parameter container/task to a TEnv
969// instance (steering card/setup file).
970// The key to search for in the file should be of the syntax:
971//    prefix.vname
972// While vname is a name which is specific for a single setup date
973// (variable) of this container and prefix is something like:
974//    evtloopname.name
975// While name is the name of the containers/tasks in the parlist/tasklist
976//
977// eg.  Job4.MImgCleanStd.CleaningLevel1:  3.0
978//      Job4.MImgCleanStd.CleaningLevel2:  2.5
979//
980// If this cannot be found the next step is to search for
981//      MImgCleanStd.CleaningLevel1:  3.0
982// And if this doesn't exist, too, we search for:
983//      CleaningLevel1:  3.0
984//
985// Warning: The programmer is responsible for the names to be unique in
986//          all Mars classes.
987//
988Bool_t MParList::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
989{
990    MParContainer *cont = NULL;
991
992    MIter Next(fContainer);
993    while ((cont=Next()))
994        if (!cont->WriteEnv(env, prefix, print))
995            return kFALSE;
996    return kTRUE;
997}
998
999// --------------------------------------------------------------------------
1000//
1001// Can be used to create an iterator over all containers, eg:
1002//   MParList plist;
1003//   TIter Next(plist); // Be aware: Use a object here rather than a pointer!
1004//   TObject *o=0;
1005//   while ((o=Next()))
1006//   {
1007//       [...]
1008//   }
1009//
1010MParList::operator TIterator*() const
1011{
1012    return new TOrdCollectionIter(fContainer);
1013}
Note: See TracBrowser for help on using the repository browser.