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

Last change on this file since 1794 was 1794, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 13.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.h> // ofstream, AsciiWrite
41
42#include <TROOT.h> // TROOT::Identlevel
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
53#ifndef __COSY__
54#include "MEvtLoop.h" // gListOfPrimitives
55#else
56TList *gListOfPrimitives;
57#endif
58
59ClassImp(MParContainer);
60
61// --------------------------------------------------------------------------
62//
63// MParContainer copy ctor
64//
65MParContainer::MParContainer(const MParContainer &named)
66{
67 fName = named.fName;
68 fTitle = named.fTitle;
69
70 fLog = named.fLog;
71
72 fReadyToSave = named.fReadyToSave;
73}
74
75// --------------------------------------------------------------------------
76//
77// MParContainer assignment operator.
78//
79MParContainer& MParContainer::operator=(const MParContainer& rhs)
80{
81 if (this == &rhs)
82 return *this;
83
84 TObject::operator=(rhs);
85
86 fName = rhs.fName;
87 fTitle = rhs.fTitle;
88
89 fLog = rhs.fLog;
90 fReadyToSave = rhs.fReadyToSave;
91
92 return *this;
93}
94
95// --------------------------------------------------------------------------
96//
97// Make a clone of an object using the Streamer facility.
98// If newname is specified, this will be the name of the new object
99//
100TObject *MParContainer::Clone(const char *newname) const
101{
102
103 MParContainer *named = (MParContainer*)TObject::Clone();
104 if (newname && strlen(newname)) named->SetName(newname);
105 return named;
106}
107
108// --------------------------------------------------------------------------
109//
110// Compare two MParContainer objects. Returns 0 when equal, -1 when this is
111// smaller and +1 when bigger (like strcmp).
112//
113Int_t MParContainer::Compare(const TObject *obj) const
114{
115 if (this == obj) return 0;
116 return fName.CompareTo(obj->GetName());
117}
118
119// --------------------------------------------------------------------------
120//
121// Copy this to obj.
122//
123void MParContainer::Copy(TObject &obj)
124{
125 MParContainer &cont = (MParContainer&)obj;
126
127 TObject::Copy(obj);
128
129 cont.fName = fName;
130 cont.fTitle = fTitle;
131
132 cont.fLog = fLog;
133 cont.fReadyToSave = fReadyToSave;
134}
135
136// --------------------------------------------------------------------------
137//
138// Encode MParContainer into output buffer.
139//
140void MParContainer::FillBuffer(char *&buffer)
141{
142 fName.FillBuffer(buffer);
143 fTitle.FillBuffer(buffer);
144}
145
146// --------------------------------------------------------------------------
147//
148// Return a unique name for this container. It is created from
149// the container name and the unique Id. (This is mostly used
150// in the StreamPrimitive member functions)
151//
152const TString MParContainer::GetUniqueName() const
153{
154 TString ret = ToLower(fName);
155
156 if (isdigit(ret[ret.Length()-1]))
157 ret+="_";
158
159 ret+=GetUniqueID();
160
161 return ret;
162}
163
164// --------------------------------------------------------------------------
165//
166// List MParContainer name and title.
167//
168void MParContainer::ls(Option_t *) const
169{
170 TROOT::IndentLevel();
171 *fLog << all << GetDescriptor() << " " << GetTitle() << ": kCanDelete=";
172 *fLog << Int_t(TestBit(kCanDelete)) << endl;
173}
174
175// --------------------------------------------------------------------------
176//
177// Print MParContainer name and title.
178//
179void MParContainer::Print(Option_t *) const
180{
181 *fLog << all << GetDescriptor() << " " << GetTitle() << endl;
182}
183
184// --------------------------------------------------------------------------
185//
186// Change (i.e. set) the name of the MParContainer.
187// WARNING !!
188// If the object is a member of a THashTable, THashList container
189// The HashTable must be Rehashed after SetName
190// For example the list of objects in the current directory is a THashList
191//
192void MParContainer::SetName(const char *name)
193{
194 fName = name;
195 ResetBit(kIsSavedAsPrimitive);
196 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
197}
198
199// --------------------------------------------------------------------------
200//
201// Change (i.e. set) all the MParContainer parameters (name and title).
202// See also WARNING in SetName
203//
204void MParContainer::SetObject(const char *name, const char *title)
205{
206 fName = name;
207 fTitle = title;
208 ResetBit(kIsSavedAsPrimitive);
209 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
210}
211
212// --------------------------------------------------------------------------
213//
214// Change (i.e. set) the title of the MParContainer.
215//
216void MParContainer::SetTitle(const char *title)
217{
218 fTitle = title;
219 ResetBit(kIsSavedAsPrimitive);
220 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
221}
222
223// --------------------------------------------------------------------------
224//
225// Return size of the MParContainer part of the TObject.
226//
227Int_t MParContainer::Sizeof() const
228{
229 Int_t nbytes = fName.Sizeof() + fTitle.Sizeof();
230 return nbytes;
231}
232
233// --------------------------------------------------------------------------
234//
235// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
236// container, overload this function.
237//
238void MParContainer::AsciiRead(ifstream &fin)
239{
240 *fLog << warn << "To use the the ascii input of " << GetName();
241 *fLog << " you have to overload " << ClassName() << "::AsciiRead." << endl;
242}
243
244// --------------------------------------------------------------------------
245//
246// Write out a data member given as a TDataMember object to an output stream.
247//
248Bool_t MParContainer::WriteDataMember(ostream &out, const TDataMember *member, Double_t scale) const
249{
250 if (!member)
251 return kFALSE;
252
253 if (!member->IsPersistent() || member->Property()&kIsStatic)
254 return kFALSE;
255
256 /*const*/ TMethodCall *call = ((TDataMember*)member)->GetterMethod(); //FIXME: Root
257 if (!call)
258 {
259 *fLog << warn << "Sorry, no getter method found for " << member->GetName() << endl;
260 return kFALSE;
261 }
262
263 // For debugging: out << member->GetName() << ":";
264
265 switch (call->ReturnType())
266 {
267 case TMethodCall::kLong:
268 Long_t l;
269 call->Execute((void*)this, l); // FIXME: const, root
270 out << l << " ";
271 return kTRUE;
272
273 case TMethodCall::kDouble:
274 Double_t d;
275 call->Execute((void*)this, d); // FIXME: const, root
276 out << (scale*d) << " ";
277 return kTRUE;
278
279 default:
280 //case TMethodCall::kString:
281 //case TMethodCall::kOther:
282 /* someone may want to enhance this? */
283 return kFALSE;
284 }
285}
286
287// --------------------------------------------------------------------------
288//
289// Write out a data member given by name to an output stream.
290//
291Bool_t MParContainer::WriteDataMember(ostream &out, const char *member, Double_t scale) const
292{
293 /*const*/ TClass *cls = IsA()->GetBaseDataMember(member);
294 if (!cls)
295 return kFALSE;
296
297 return WriteDataMember(out, cls->GetDataMember(member), scale);
298}
299
300// --------------------------------------------------------------------------
301//
302// Write out a data member from a given TList of TDataMembers.
303// returns kTRUE when at least one member was successfully written
304//
305Bool_t MParContainer::WriteDataMember(ostream &out, const TList *list) const
306{
307 Bool_t rc = kFALSE;
308
309 TDataMember *data = NULL;
310
311 TIter Next(list);
312 while ((data=(TDataMember*)Next()))
313 rc |= WriteDataMember(out, data);
314
315 return rc;
316}
317
318// --------------------------------------------------------------------------
319//
320// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
321// container, you may overload this function. If you don't overload it
322// the data member of a class are written to the file in the order of
323// appearance in the class header (be more specfic: root dictionary)
324// Only data members which are of integer (Bool_t, Int_t, ...) or
325// floating point (Float_t, Double_t, ...) type are written.
326// returns kTRUE when at least one member was successfully written
327//
328Bool_t MParContainer::AsciiWrite(ostream &out) const
329{
330 // *fLog << warn << "To use the the ascii output of " << GetName();
331 // *fLog << " you have to overload " << ClassName() << "::AsciiWrite." << endl;
332
333 Bool_t rc = WriteDataMember(out, IsA()->GetListOfDataMembers());
334
335 TIter NextBaseClass(IsA()->GetListOfBases());
336 TBaseClass *base;
337 while ((base = (TBaseClass*) NextBaseClass()))
338 {
339 /*const*/ TClass *cls = base->GetClassPointer();
340
341 if (!cls)
342 continue;
343
344 if (cls->GetClassVersion())
345 rc |= WriteDataMember(out, cls->GetListOfDataMembers());
346 }
347
348 return rc;
349}
350
351TMethodCall *MParContainer::GetterMethod(const char *name) const
352{
353 TClass *cls = IsA()->GetBaseDataMember(name);
354 if (cls)
355 {
356 TDataMember *member = cls->GetDataMember(name);
357 if (!member)
358 {
359 *fLog << err << "Datamember '" << name << "' not in " << GetDescriptor() << endl;
360 return NULL;
361 }
362
363 TMethodCall *call = member->GetterMethod();
364 if (call)
365 return call;
366 }
367
368 *fLog << warn << "No standard access for '" << name << "' in ";
369 *fLog << GetDescriptor() << " or one of its base classes." << endl;
370
371 TMethodCall *call = NULL;
372
373 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
374 *fLog << "::Get" << name << "' instead <LEAKS MEMORY>" << endl;
375 call = new TMethodCall(IsA(), (TString)"Get"+name, "");
376 if (call->GetMethod())
377 return call;
378
379 delete call;
380
381 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
382 *fLog << "::" << name << "' instead <LEAKS MEMORY>" << endl;
383 call = new TMethodCall(IsA(), name, "");
384 if (call->GetMethod())
385 return call;
386
387 delete call;
388
389 *fLog << err << "Sorry, no getter method found for " << name << endl;
390 return NULL;
391}
392
393// --------------------------------------------------------------------------
394//
395// Implementation of SavePrimitive. Used to write the call to a constructor
396// to a macro. In the original root implementation it is used to write
397// gui elements to a macro-file.
398//
399void MParContainer::SavePrimitive(ofstream &out, Option_t *o)
400{
401 static UInt_t uid = 0;
402
403 if (IsSavedAsPrimitive())
404 return;
405
406 SetUniqueID(uid++);
407 SetBit(kIsSavedAsPrimitive);
408
409 if (gListOfPrimitives && !gListOfPrimitives->FindObject(this))
410 gListOfPrimitives->Add(this);
411
412 StreamPrimitive(out);
413}
414
415// --------------------------------------------------------------------------
416//
417// Creates the string written by SavePrimitive and returns it.
418//
419void MParContainer::StreamPrimitive(ofstream &out) const
420{
421 out << " // Using MParContainer::StreamPrimitive" << endl;
422 out << " " << ClassName() << " " << GetUniqueName() << "(\"";
423 out << fName << "\", \"" << fTitle << "\");" << endl;
424}
425
426void MParContainer::GetNames(TObjArray &arr) const
427{
428 arr.AddLast(new TNamed(fName, fTitle));
429}
430
431void MParContainer::SetNames(TObjArray &arr)
432{
433 TNamed *name = (TNamed*)arr.First();
434
435 fName = name->GetName();
436 fTitle = name->GetTitle();
437
438 delete arr.Remove(name);
439 arr.Compress();
440}
441
442// --------------------------------------------------------------------------
443//
444// Creates a new instance of this class. The idea is to create a clone of
445// this class in its initial state.
446//
447MParContainer *MParContainer::New() const
448{
449 return (MParContainer*)IsA()->New();
450}
Note: See TracBrowser for help on using the repository browser.