source: trunk/MagicSoft/Mars/mbase/MParContainer.cc@ 3500

Last change on this file since 3500 was 3183, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 18.1 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// MParContainer //
28// //
29// The MParContainer class is the base class for all MARS parameter //
30// containers. At the moment it is almost the same than ROOT's TNamed. //
31// A TNamed contains the essential elements (name, title) //
32// to identify a derived object in lists like our MParList or MTaskList. //
33// The main difference is that the name and title isn't stored and read //
34// to and from root files ("//!") //
35// //
36//////////////////////////////////////////////////////////////////////////////
37#include "MParContainer.h"
38
39#include <ctype.h> // isdigit
40#include <fstream> // ofstream, AsciiWrite
41
42#include <TEnv.h> // Env::Lookup
43#include <TClass.h> // IsA
44#include <TObjArray.h> // TObjArray
45#include <TBaseClass.h> // GetClassPointer
46#include <TMethodCall.h> // TMethodCall, AsciiWrite
47#include <TDataMember.h> // TDataMember, AsciiWrite
48#include <TVirtualPad.h> // gPad
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53TList *gListOfPrimitives; // forard declaration in MParContainer.h
54
55#undef DEBUG
56//#define DEBUG
57
58ClassImp(MParContainer);
59
60using namespace std;
61
62MParContainer::MParContainer(const char *name, const char *title) :
63 fName(name), fTitle(title), fLog(&gLog), fDisplay(NULL), fReadyToSave(kFALSE)
64{
65}
66
67MParContainer::MParContainer(const TString &name, const TString &title) :
68 fName(name), fTitle(title), fLog(&gLog), fDisplay(NULL), fReadyToSave(kFALSE)
69{
70}
71
72// --------------------------------------------------------------------------
73//
74// MParContainer copy ctor
75//
76MParContainer::MParContainer(const MParContainer &named)
77{
78 fName = named.fName;
79 fTitle = named.fTitle;
80
81 fLog = named.fLog;
82
83 fReadyToSave = named.fReadyToSave;
84
85 fDisplay = named.fDisplay;
86}
87
88MParContainer::~MParContainer()
89{
90#ifdef DEBUG
91 *fLog << all << "Deleting " << GetDescriptor() << endl;
92#endif
93}
94
95// --------------------------------------------------------------------------
96//
97// MParContainer assignment operator.
98//
99MParContainer& MParContainer::operator=(const MParContainer& rhs)
100{
101 if (this == &rhs)
102 return *this;
103
104 TObject::operator=(rhs);
105
106 fName = rhs.fName;
107 fTitle = rhs.fTitle;
108
109 fLog = rhs.fLog;
110 fReadyToSave = rhs.fReadyToSave;
111
112 return *this;
113}
114
115// --------------------------------------------------------------------------
116//
117// Make a clone of an object using the Streamer facility.
118// If newname is specified, this will be the name of the new object
119//
120TObject *MParContainer::Clone(const char *newname) const
121{
122
123 MParContainer *named = (MParContainer*)TObject::Clone();
124 if (newname && strlen(newname)) named->SetName(newname);
125 return named;
126}
127
128// --------------------------------------------------------------------------
129//
130// Compare two MParContainer objects. Returns 0 when equal, -1 when this is
131// smaller and +1 when bigger (like strcmp).
132//
133Int_t MParContainer::Compare(const TObject *obj) const
134{
135 if (this == obj) return 0;
136 return fName.CompareTo(obj->GetName());
137}
138
139// --------------------------------------------------------------------------
140//
141// Copy this to obj.
142//
143void MParContainer::Copy(TObject &obj)
144#if ROOT_VERSION_CODE > ROOT_VERSION(3,04,01)
145const
146#endif
147{
148 MParContainer &cont = (MParContainer&)obj;
149
150 TObject::Copy(obj);
151
152 cont.fName = fName;
153 cont.fTitle = fTitle;
154
155 cont.fLog = fLog;
156 cont.fReadyToSave = fReadyToSave;
157}
158
159// --------------------------------------------------------------------------
160//
161// Encode MParContainer into output buffer.
162//
163void MParContainer::FillBuffer(char *&buffer)
164{
165 fName.FillBuffer(buffer);
166 fTitle.FillBuffer(buffer);
167}
168
169// --------------------------------------------------------------------------
170//
171// Returns the name of the object. If the name of the object is not the
172// class name it returns the object name and in []-brackets the class name.
173//
174const char *MParContainer::GetDescriptor() const
175{
176 //
177 // Because it returns a (const char*) we cannot return a casted
178 // local TString. The pointer would - immediatly after return -
179 // point to a random memory segment, because the TString has gone.
180 //
181 return fName==ClassName() ? ClassName() : Form("%s [%s]", fName.Data(), ClassName());
182}
183
184// --------------------------------------------------------------------------
185//
186// Return a unique name for this container. It is created from
187// the container name and the unique Id. (This is mostly used
188// in the StreamPrimitive member functions)
189//
190const TString MParContainer::GetUniqueName() const
191{
192 TString ret = ToLower(fName);
193
194 if (isdigit(ret[ret.Length()-1]))
195 ret+="_";
196
197 ret+=GetUniqueID();
198
199 return ret;
200}
201
202// --------------------------------------------------------------------------
203//
204// List MParContainer name and title.
205//
206void MParContainer::ls(Option_t *) const
207{
208 TROOT::IndentLevel();
209 *fLog << all << GetDescriptor() << " " << GetTitle() << ": kCanDelete=";
210 *fLog << Int_t(TestBit(kCanDelete)) << endl;
211}
212
213// --------------------------------------------------------------------------
214//
215// Print MParContainer name and title.
216//
217void MParContainer::Print(Option_t *) const
218{
219 *fLog << all << GetDescriptor() << " " << GetTitle() << endl;
220}
221
222// --------------------------------------------------------------------------
223//
224// Change (i.e. set) the name of the MParContainer.
225// WARNING !!
226// If the object is a member of a THashTable, THashList container
227// The HashTable must be Rehashed after SetName
228// For example the list of objects in the current directory is a THashList
229//
230void MParContainer::SetName(const char *name)
231{
232 fName = name;
233 ResetBit(kIsSavedAsPrimitive);
234 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
235}
236
237// --------------------------------------------------------------------------
238//
239// Change (i.e. set) all the MParContainer parameters (name and title).
240// See also WARNING in SetName
241//
242void MParContainer::SetObject(const char *name, const char *title)
243{
244 fName = name;
245 fTitle = title;
246 ResetBit(kIsSavedAsPrimitive);
247 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
248}
249
250// --------------------------------------------------------------------------
251//
252// Change (i.e. set) the title of the MParContainer.
253//
254void MParContainer::SetTitle(const char *title)
255{
256 fTitle = title;
257 ResetBit(kIsSavedAsPrimitive);
258 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
259}
260
261// --------------------------------------------------------------------------
262//
263// Return size of the MParContainer part of the TObject.
264//
265Int_t MParContainer::Sizeof() const
266{
267 Int_t nbytes = fName.Sizeof() + fTitle.Sizeof();
268 return nbytes;
269}
270
271// --------------------------------------------------------------------------
272//
273// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
274// container, overload this function.
275//
276void MParContainer::AsciiRead(ifstream &fin)
277{
278 *fLog << warn << "To use the the ascii input of " << GetName();
279 *fLog << " you have to overload " << ClassName() << "::AsciiRead." << endl;
280}
281
282// --------------------------------------------------------------------------
283//
284// Write out a data member given as a TDataMember object to an output stream.
285//
286Bool_t MParContainer::WriteDataMember(ostream &out, const TDataMember *member, Double_t scale) const
287{
288 if (!member)
289 return kFALSE;
290
291 if (!member->IsPersistent() || member->Property()&kIsStatic)
292 return kFALSE;
293
294 /*const*/ TMethodCall *call = ((TDataMember*)member)->GetterMethod(); //FIXME: Root
295 if (!call)
296 {
297 *fLog << warn << "Sorry, no getter method found for " << member->GetName() << endl;
298 return kFALSE;
299 }
300
301 // For debugging: out << member->GetName() << ":";
302
303 switch (call->ReturnType())
304 {
305 case TMethodCall::kLong:
306 Long_t l;
307 call->Execute((void*)this, l); // FIXME: const, root
308 out << l << " ";
309 return kTRUE;
310
311 case TMethodCall::kDouble:
312 Double_t d;
313 call->Execute((void*)this, d); // FIXME: const, root
314 out << (scale*d) << " ";
315 return kTRUE;
316
317 default:
318 //case TMethodCall::kString:
319 //case TMethodCall::kOther:
320 /* someone may want to enhance this? */
321 return kFALSE;
322 }
323}
324
325// --------------------------------------------------------------------------
326//
327// Write out a data member given by name to an output stream.
328//
329Bool_t MParContainer::WriteDataMember(ostream &out, const char *member, Double_t scale) const
330{
331 /*const*/ TClass *cls = IsA()->GetBaseDataMember(member);
332 if (!cls)
333 return kFALSE;
334
335 return WriteDataMember(out, cls->GetDataMember(member), scale);
336}
337
338// --------------------------------------------------------------------------
339//
340// Write out a data member from a given TList of TDataMembers.
341// returns kTRUE when at least one member was successfully written
342//
343Bool_t MParContainer::WriteDataMember(ostream &out, const TList *list) const
344{
345 Bool_t rc = kFALSE;
346
347 TDataMember *data = NULL;
348
349 TIter Next(list);
350 while ((data=(TDataMember*)Next()))
351 rc |= WriteDataMember(out, data);
352
353 return rc;
354}
355
356// --------------------------------------------------------------------------
357//
358// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
359// container, you may overload this function. If you don't overload it
360// the data member of a class are written to the file in the order of
361// appearance in the class header (be more specfic: root dictionary)
362// Only data members which are of integer (Bool_t, Int_t, ...) or
363// floating point (Float_t, Double_t, ...) type are written.
364// returns kTRUE when at least one member was successfully written
365//
366Bool_t MParContainer::AsciiWrite(ostream &out) const
367{
368 // *fLog << warn << "To use the the ascii output of " << GetName();
369 // *fLog << " you have to overload " << ClassName() << "::AsciiWrite." << endl;
370
371 Bool_t rc = WriteDataMember(out, IsA()->GetListOfDataMembers());
372
373 TIter NextBaseClass(IsA()->GetListOfBases());
374 TBaseClass *base;
375 while ((base = (TBaseClass*) NextBaseClass()))
376 {
377 /*const*/ TClass *cls = base->GetClassPointer();
378
379 if (!cls)
380 continue;
381
382 if (cls->GetClassVersion())
383 rc |= WriteDataMember(out, cls->GetListOfDataMembers());
384 }
385
386 return rc;
387}
388
389TMethodCall *MParContainer::GetterMethod(const char *name) const
390{
391 TClass *cls = IsA()->GetBaseDataMember(name);
392 if (cls)
393 {
394 TDataMember *member = cls->GetDataMember(name);
395 if (!member)
396 {
397 *fLog << err << "Datamember '" << name << "' not in " << GetDescriptor() << endl;
398 return NULL;
399 }
400
401 TMethodCall *call = member->GetterMethod();
402 if (call)
403 return call;
404 }
405
406 *fLog << warn << "No standard access for '" << name << "' in ";
407 *fLog << GetDescriptor() << " or one of its base classes." << endl;
408
409 TMethodCall *call = NULL;
410
411 *fLog << warn << "Trying to find MethodCall '" << ClassName();
412 *fLog << "::Get" << name << "' instead <LEAKS MEMORY>" << endl;
413 call = new TMethodCall(IsA(), (TString)"Get"+name, "");
414 if (call->GetMethod())
415 return call;
416
417 delete call;
418
419 *fLog << warn << "Trying to find MethodCall '" << ClassName();
420 *fLog << "::" << name << "' instead <LEAKS MEMORY>" << endl;
421 call = new TMethodCall(IsA(), name, "");
422 if (call->GetMethod())
423 return call;
424
425 delete call;
426
427 *fLog << err << "Sorry, no getter method found for " << name << endl;
428 return NULL;
429}
430
431// --------------------------------------------------------------------------
432//
433// Implementation of SavePrimitive. Used to write the call to a constructor
434// to a macro. In the original root implementation it is used to write
435// gui elements to a macro-file.
436//
437void MParContainer::SavePrimitive(ofstream &out, Option_t *o)
438{
439 static UInt_t uid = 0;
440
441 if (IsSavedAsPrimitive())
442 return;
443
444 SetUniqueID(uid++);
445 SetBit(kIsSavedAsPrimitive);
446
447 if (gListOfPrimitives && !gListOfPrimitives->FindObject(this))
448 gListOfPrimitives->Add(this);
449
450 StreamPrimitive(out);
451}
452
453// --------------------------------------------------------------------------
454//
455// Creates the string written by SavePrimitive and returns it.
456//
457void MParContainer::StreamPrimitive(ofstream &out) const
458{
459 out << " // Using MParContainer::StreamPrimitive" << endl;
460 out << " " << ClassName() << " " << GetUniqueName() << "(\"";
461 out << fName << "\", \"" << fTitle << "\");" << endl;
462}
463
464void MParContainer::GetNames(TObjArray &arr) const
465{
466 arr.AddLast(new TNamed(fName, fTitle));
467}
468
469void MParContainer::SetNames(TObjArray &arr)
470{
471 TNamed *name = (TNamed*)arr.First();
472
473 fName = name->GetName();
474 fTitle = name->GetTitle();
475
476 delete arr.Remove(name);
477 arr.Compress();
478}
479
480// --------------------------------------------------------------------------
481//
482// Creates a new instance of this class. The idea is to create a clone of
483// this class in its initial state.
484//
485MParContainer *MParContainer::New() const
486{
487 return (MParContainer*)IsA()->New();
488}
489
490// --------------------------------------------------------------------------
491//
492// Read the contents/setup of a parameter container/task from a TEnv
493// instance (steering card/setup file).
494// The key to search for in the file should be of the syntax:
495// prefix.vname
496// While vname is a name which is specific for a single setup date
497// (variable) of this container and prefix is something like:
498// evtloopname.name
499// While name is the name of the containers/tasks in the parlist/tasklist
500//
501// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
502// Job4.MImgCleanStd.CleaningLevel2: 2.5
503//
504// If this cannot be found the next step is to search for
505// MImgCleanStd.CleaningLevel1: 3.0
506// And if this doesn't exist, too, we should search for:
507// CleaningLevel1: 3.0
508//
509// Warning: The programmer is responsible for the names to be unique in
510// all Mars classes.
511//
512Bool_t MParContainer::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
513{
514 if (!IsEnvDefined(env, prefix, "", print))
515 return kFALSE;
516
517 *fLog << warn << "WARNING - Resource " << prefix+fName << " found, but no " << ClassName() << "::ReadEnv." << endl;
518 return kTRUE;
519}
520
521// --------------------------------------------------------------------------
522//
523// Write the contents/setup of a parameter container/task to a TEnv
524// instance (steering card/setup file).
525// The key to search for in the file should be of the syntax:
526// prefix.vname
527// While vname is a name which is specific for a single setup date
528// (variable) of this container and prefix is something like:
529// evtloopname.name
530// While name is the name of the containers/tasks in the parlist/tasklist
531//
532// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
533// Job4.MImgCleanStd.CleaningLevel2: 2.5
534//
535// If this cannot be found the next step is to search for
536// MImgCleanStd.CleaningLevel1: 3.0
537// And if this doesn't exist, too, we should search for:
538// CleaningLevel1: 3.0
539//
540// Warning: The programmer is responsible for the names to be unique in
541// all Mars classes.
542//
543Bool_t MParContainer::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
544{
545 if (!IsEnvDefined(env, prefix, "", print))
546 return kFALSE;
547
548 *fLog << warn << "WARNING - Resource " << prefix+fName << " found, but " << ClassName() << "::WriteEnv not overloaded." << endl;
549 return kTRUE;
550}
551
552Bool_t MParContainer::IsEnvDefined(const TEnv &env, TString prefix, TString postfix, Bool_t print) const
553{
554 if (!postfix.IsNull())
555 postfix.Insert(0, ".");
556
557 return IsEnvDefined(env, prefix+postfix, print);
558}
559
560Bool_t MParContainer::IsEnvDefined(const TEnv &env, TString name, Bool_t print) const
561{
562 if (print)
563 *fLog << all << GetDescriptor() << " - " << name << "... " << flush;
564
565 if (!((TEnv&)env).Defined(name))
566 {
567 if (print)
568 *fLog << "not found." << endl;
569 return kFALSE;
570 }
571
572 if (print)
573 *fLog << "found." << endl;
574
575 return kTRUE;
576}
577
578Int_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, Int_t dflt) const
579{
580 return GetEnvValue(env, prefix+"."+postfix, dflt);
581}
582
583Double_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, Double_t dflt) const
584{
585 return GetEnvValue(env, prefix+"."+postfix, dflt);
586}
587
588const char *MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, const char *dflt) const
589{
590 return GetEnvValue(env, prefix+"."+postfix, dflt);
591}
592
593Int_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, Int_t dflt) const
594{
595 return ((TEnv&)env).GetValue(prefix, dflt);
596}
597
598Double_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, Double_t dflt) const
599{
600 return ((TEnv&)env).GetValue(prefix, dflt);
601}
602
603const char *MParContainer::GetEnvValue(const TEnv &env, TString prefix, const char *dflt) const
604{
605 return ((TEnv&)env).GetValue(prefix, dflt);
606}
Note: See TracBrowser for help on using the repository browser.