GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4Parameter.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4Parameter.h"
15 
16 #include <cstring>
17 #include <cstdlib>
18 #include <iostream>
19 
20 #include "TROOT.h"
21 #include "TUrl.h"
22 #include "TList.h"
23 #include "TObjArray.h"
24 #include "TDataMember.h"
25 #include "TBaseClass.h"
26 #include "TDataType.h"
27 #include "TDatime.h"
28 #include "TArrayI.h"
29 #include "TArrayD.h"
30 
31 #include "TGo4Log.h"
32 #include "TGo4ParameterMember.h"
33 #include "TGo4ParameterStatus.h"
34 
36  TNamed()
37 {
38 }
39 
40 TGo4Parameter::TGo4Parameter(const char *name, const char *title) :
41  TNamed(name ? name : "Parameter", title)
42 {
43  GO4TRACE((12,"TGo4Parameter ::TGo4Parameter (const char*, const char*)",__LINE__, __FILE__));
44 }
45 
46 void TGo4Parameter::Print(Option_t *dummy) const
47 {
48  // this trick is needed since root defines Print as const function...
49  TGo4Parameter *const localthis= const_cast<TGo4Parameter *const>(this);
50  localthis->PrintParameter();
51 }
52 
53 Int_t TGo4Parameter::PrintParameter(Text_t*, Int_t)
54 {
55  TObjArray items;
56  GetMemberValues(&items);
57 
58  TGo4Status::PrintLine("Parameter name: %s class %s", GetName(), ClassName());
59 
60  TIter iter(&items);
61 
62  TROOT::IncreaseDirLevel();
63 
64  while (auto info = (TGo4ParameterMember*) iter())
65  info->Print();
66 
67  TROOT::DecreaseDirLevel();
68 
69  return 0;
70 }
71 
73 {
74  GO4TRACE((12,"TGo4Parameter ::~TGo4Parameter ()",__LINE__, __FILE__));
75 }
76 
78 {
79  if (!rhs) return kFALSE;
80 
81  if (rhs->IsA() != IsA()) {
82  std::cout << "GO4> !!! ERROR: Wrong parameter class is used in TGo4Parameter::UpdateFrom() method!!!" << std::endl;
83  std::cout << "GO4> !!! ERROR: One cannot update " << IsA()->GetName() << " class from " << rhs->IsA()->GetName() << std::endl;
84  std::cout << "GO4> !!! ERROR: Implement your custom UpdateFrom() method" << std::endl;
85  return kFALSE;
86  }
87 
88  TObjArray items;
89 
90  rhs->GetMemberValues(&items);
91 
92  return SetMemberValues(&items);
93 }
94 
95 Bool_t TGo4Parameter::UpdateFromUrl(const char *rest_url_opt)
96 {
97  TGo4Parameter *clone = (TGo4Parameter*) Clone();
98 
99  TObjArray items;
100  clone->GetMemberValues(&items);
101 
102  TUrl url;
103  url.SetOptions(rest_url_opt);
104 
105  TIter next(&items);
106 
107  while (auto member = (TGo4ParameterMember*) next()) {
108  TString dummy;
109  const char *optvalue = url.GetValueFromOptions(member->GetFullName(dummy)); //member->GetName());
110  if (optvalue) {
111  TGo4Log::Info("Par:%s member %s newvalue %s", GetName(), member->GetFullName(dummy), optvalue);
112  member->SetStrValue(optvalue);
113  }
114  }
115 
116  clone->SetMemberValues(&items);
117 
118  Bool_t res = UpdateFrom(clone);
119  delete clone;
120  return res;
121 }
122 
123 
124 void TGo4Parameter::Clear(Option_t *)
125 {
126  // default clear, may be implemented by user
127  std::cout << "GO4> !!! Default TGo4Parameter::Clear() method is used." << std::endl;
128  std::cout << "GO4> !!! You probably need to overwrite Clear() method for your class" << IsA()->GetName() << std::endl;
129 
130  TObjArray items;
131  GetMemberValues(&items);
132 
133  TIter iter(&items);
134 
135  while (auto info = (TGo4ParameterMember*) iter())
136  info->SetToZero();
137 
138  SetMemberValues(&items);
139 }
140 
141 void TGo4Parameter::GetMemberValues(TObjArray *fItems)
142 {
143  if (!fItems)
144  return;
145  fItems->SetOwner(kTRUE); // created objects owned by collection
146  GetMemberValues(fItems, IsA(), (char *) this, 0);
147 }
148 
149 Bool_t TGo4Parameter::SetMemberValues(TObjArray *items)
150 {
151  if (!items) return kFALSE;
152 
153  Int_t indx = 0;
154 
155  return SetMemberValues(items, indx, IsA(), (char *) this, 0);
156 }
157 
158 
159 void TGo4Parameter::GetMemberValues(TObjArray *fItems, TClass *cl, char *ptr, unsigned long int cloffset)
160 {
161  if (!fItems || !cl || !ptr) return;
162 
163  TIter iter(cl->GetListOfDataMembers());
164  Int_t lastmemberid = -1;
165  if (fItems->GetLast() >= 0)
166  lastmemberid = ((TGo4ParameterMember*) fItems->Last())->GetMemberId();
167 
168  while (auto obj = iter()) {
169  auto member = dynamic_cast<TDataMember *>(obj);
170  if (!member) continue;
171  const char *memtypename = member->GetFullTypeName();
172  Int_t memtypeid = 0;
173 
174  // do not edit IsA info
175  if(strcmp(memtypename, "TClass*") == 0) continue;
176  // skip for a moment all types which are not basic types
177 
178  Int_t arraydim = member->GetArrayDim();
179  if (arraydim > 2) continue;
180 
181  Int_t maxindex1 = 1, maxindex2 = 1;
182 
183  switch(arraydim) {
184  case 1:
185  maxindex1 = member->GetMaxIndex(0);
186  break;
187  case 2:
188  maxindex1 = member->GetMaxIndex(0);
189  maxindex2 = member->GetMaxIndex(1);
190  break;
191  } // switch()
192 
193  TArrayI* arri = nullptr;
194  TArrayD* arrd = nullptr;
195 
196  if (strcmp(memtypename,"TString") == 0) {
198  } else
199  if (strcmp(memtypename,"TGo4Fitter*") == 0) {
201  } else
202  if (strcmp(memtypename,"TArrayI") == 0) {
203  memtypeid = kInt_t;
204  memtypename = "Int_t";
205  if ((maxindex1>1) || (maxindex2>1)) continue;
206  arri = (TArrayI*) (ptr + cloffset + member->GetOffset());
207  arraydim = 1;
208  maxindex1 = arri->GetSize();
209  maxindex2 = 1;
210  } else
211  if (strcmp(memtypename,"TArrayD") == 0) {
212  memtypeid = kDouble_t;
213  memtypename = "Double_t";
214  if ((maxindex1>1) || (maxindex2>1)) continue;
215  arrd = (TArrayD*) (ptr + cloffset + member->GetOffset());
216  arraydim = 1;
217  maxindex1 = arrd->GetSize();
218  maxindex2 = 1;
219  } else {
220  if (!member->IsBasic()) continue;
221  memtypeid = member->GetDataType()->GetType();
222  }
223 
224  // add extra filed with array size
225  if (arri || arrd) {
226  TGo4ParameterMember* info = new TGo4ParameterMember(member->GetName(), member->GetTitle());
227 
228  info->SetMemberId(lastmemberid++);
229 
230  info->SetType("TArray", TGo4ParameterMember::kTArray_t);
231  info->SetVisible(kFALSE);
232  //info->SetArrayIndexes(0, 0, 0);
233  info->SetIntValue(maxindex1);
234 
235  fItems->Add(info);
236  }
237 
238  lastmemberid++;
239 
240  for (Int_t ix1 = 0; ix1 < maxindex1; ix1++)
241  for (Int_t ix2 = 0; ix2 < maxindex2; ix2++) {
242  TGo4ParameterMember *info = new TGo4ParameterMember(member->GetName(), member->GetTitle());
243  fItems->Add(info);
244 
245  info->SetMemberId(lastmemberid);
246 
247  info->SetType(memtypename, memtypeid);
248 
249  info->SetVisible((ix1 == 0) && (ix2 == 0));
250 
251  info->SetArrayIndexes(arraydim, ix1, ix2);
252 
253  char *addr = ptr + cloffset + member->GetOffset() + (ix1 * maxindex2 + ix2) * member->GetUnitSize();
254  if (arri)
255  addr = (char *)(arri->GetArray() + ix1);
256  if (arrd)
257  addr = (char *)(arrd->GetArray() + ix1);
258 
259  info->SetValue(addr);
260  }
261  }
262 
263  // expand base classes
264  TIter cliter(cl->GetListOfBases());
265  while(auto obj = cliter()) {
266  TBaseClass* baseclass = dynamic_cast<TBaseClass*>(obj);
267  if (!baseclass) continue;
268  TClass *bclass = baseclass->GetClassPointer();
269  if(!bclass) continue;
270  if(strcmp(bclass->GetName(), "TGo4Parameter") == 0) continue;
271  if(strcmp(bclass->GetName(), "TNamed") == 0) continue;
272 
273  GetMemberValues(fItems, bclass, ptr, cloffset + baseclass->GetDelta());
274  }
275 }
276 
277 Int_t TGo4Parameter::FindArrayLength(TObjArray *items, Int_t &itemsindx, TDataMember *member)
278 {
279  TGo4ParameterMember* info = dynamic_cast<TGo4ParameterMember*> (items->At(itemsindx++));
280  if (!info) return -1;
281  if (strcmp(info->GetName(), member->GetName()) != 0) return -1;
282  if (strcmp(info->GetTitle(), member->GetTitle()) != 0) return -1;
283  if (info->GetTypeId() != TGo4ParameterMember::kTArray_t) return -1;
284  return info->GetIntValue();
285 }
286 
287 
288 Bool_t TGo4Parameter::SetMemberValues(TObjArray *items, Int_t &itemsindx, TClass *cl, char *ptr, unsigned long int cloffset)
289 {
290  if (!items || !cl || !ptr) return kFALSE;
291 
292  TIter iter(cl->GetListOfDataMembers());
293 
294  while (auto obj = iter()) {
295  auto member = dynamic_cast<TDataMember *>(obj);
296  if (!member) continue;
297  const char *memtypename = member->GetFullTypeName();
298  Int_t memtypeid = 0;
299 
300  // do not edit IsA info
301  if(strcmp(memtypename, "TClass*") == 0) continue;
302  // skip for a moment all types which are not basic types
303 
304  Int_t arraydim = member->GetArrayDim();
305  if (arraydim>2) continue;
306 
307  Int_t maxindex1 = 1, maxindex2 = 1;
308 
309  switch(arraydim) {
310  case 1:
311  maxindex1 = member->GetMaxIndex(0);
312  break;
313  case 2:
314  maxindex1 = member->GetMaxIndex(0);
315  maxindex2 = member->GetMaxIndex(1);
316  break;
317  } // switch()
318 
319  TArrayI* arri = nullptr;
320  TArrayD* arrd = nullptr;
321 
322  if (strcmp(memtypename, "TString") == 0) {
324  } else
325  if (strcmp(memtypename, "TGo4Fitter*") == 0) {
327  } else
328  if (strcmp(memtypename, "TArrayI") == 0) {
329  memtypeid = kInt_t;
330  memtypename = "Int_t";
331  if ((maxindex1>1) || (maxindex2>1)) continue;
332  arri = (TArrayI*) (ptr + cloffset + member->GetOffset());
333  arraydim = 1;
334  maxindex1 = FindArrayLength(items, itemsindx, member); // here we need to define index ourself
335  maxindex2 = 1;
336  if (maxindex1<0) return kFALSE;
337  if (arri->GetSize()!=maxindex1) arri->Set(maxindex1);
338  } else
339  if (strcmp(memtypename,"TArrayD") == 0) {
340  memtypeid = kDouble_t;
341  memtypename = "Double_t";
342  if ((maxindex1>1) || (maxindex2>1)) continue;
343  arrd = (TArrayD*) (ptr + cloffset + member->GetOffset());
344  arraydim = 1;
345  maxindex1 = FindArrayLength(items, itemsindx, member); // here we need to define index ourself
346  maxindex2 = 1;
347  if (maxindex1<0) return kFALSE;
348  if (arrd->GetSize()!=maxindex1) arrd->Set(maxindex1);
349  } else {
350  if (!member->IsBasic()) continue;
351  memtypeid = member->GetDataType()->GetType();
352  }
353 
354  for (Int_t ix1 = 0; ix1 < maxindex1; ix1++)
355  for (Int_t ix2 = 0; ix2 < maxindex2; ix2++) {
356  if (itemsindx > items->GetLast())
357  return kFALSE;
358  TGo4ParameterMember *info = dynamic_cast<TGo4ParameterMember *>(items->At(itemsindx++));
359  if (!info)
360  return kFALSE;
361 
362  if (strcmp(info->GetName(), member->GetName()) != 0)
363  return kFALSE;
364  if (strcmp(info->GetTitle(), member->GetTitle()) != 0)
365  return kFALSE;
366 
367  if (strcmp(info->GetTypeName(), memtypename) != 0)
368  return kFALSE;
369  if (info->GetTypeId() != memtypeid)
370  return kFALSE;
371 
372  if (!info->CheckArrayIndexes(arraydim, ix1, ix2))
373  return kFALSE;
374 
375  char *addr = ptr + cloffset + member->GetOffset() + (ix1 * maxindex2 + ix2) * member->GetUnitSize();
376  if (arri)
377  addr = (char *)(arri->GetArray() + ix1);
378  if (arrd)
379  addr = (char *)(arrd->GetArray() + ix1);
380 
381  info->GetValue(addr);
382  }
383  }
384 
385  // expand base classes
386  TIter cliter(cl->GetListOfBases());
387  while(auto obj = cliter()) {
388  TBaseClass* baseclass = dynamic_cast<TBaseClass*>(obj);
389  if (!baseclass) continue;
390  TClass *bclass = baseclass->GetClassPointer();
391  if(!bclass) continue;
392  if(strcmp(bclass->GetName(), "TGo4Parameter") == 0) continue;
393  if(strcmp(bclass->GetName(), "TNamed") == 0) continue;
394 
395  if (!SetMemberValues(items, itemsindx, bclass, ptr, cloffset + baseclass->GetDelta())) return kFALSE;
396  }
397 
398  return kTRUE;
399 }
400 
401 void TGo4Parameter::SavePrimitive(std::ostream &out, Option_t *opt)
402 {
403  static int cnt = 0;
404  TString varname = TString::Format("param%d", cnt++);
405  Bool_t savemacro = opt && strstr(opt, "savemacro");
406 
407  if (savemacro) {
408  out << TString::Format(" %s* %s = (%s*) go4->GetParameter(\"%s\",\"%s\");",
409  ClassName(), varname.Data(), ClassName(), GetName(), ClassName()) << std::endl << std::endl;
410  out << TString::Format(" if (!%s) {", varname.Data()) << std::endl;
411  out << TString::Format(" TGo4Log::Error(\"Could not find parameter %s of class %s\");", GetName(), ClassName()) << std::endl;
412  out << " return;" << std::endl;
413  out << " }" << std::endl << std::endl;
414  out << TString::Format(" TGo4Log::Info(\"Set parameter %s as saved at %s\");", GetName(), TDatime().AsString()) << std::endl << std::endl;
415  } else {
416  out << TString::Format(" %s* %s = new %s;", ClassName(), varname.Data(), ClassName()) << std::endl;
417  out << TString::Format(" %s->SetName(\"%s\");", varname.Data(), GetName()) << std::endl;
418  out << TString::Format(" %s->SetTitle(\"%s\");", varname.Data(), GetTitle()) << std::endl;
419  }
420 
421  TObjArray fitems;
422  GetMemberValues(&fitems);
423 
424  TIter iter(&fitems);
425  while (auto info = (TGo4ParameterMember*) iter()) {
426  if (info->GetTypeId() == TGo4ParameterMember::kTGo4Fitter_t) continue;
427 
428  TString membername;
429  info->GetFullName(membername);
430 
431  switch (info->GetTypeId()) {
433  out << TString::Format(" %s->%s = \"%s\";", varname.Data(), membername.Data(), info->GetStrValue()) << std::endl;
434  break;
436  out << TString::Format(" // fitter %s->%s ignored", varname.Data(), membername.Data()) << std::endl;
437  break;
439  out << TString::Format(" %s->%s.Set(%d);", varname.Data(), membername.Data(), info->GetIntValue()) << std::endl;
440  break;
441  case kBool_t:
442  out << TString::Format(" %s->%s = %s;", varname.Data(), membername.Data(), (info->GetIntValue() ? "kTRUE" : "kFALSE")) << std::endl;
443  break;
444  default:
445  out << TString::Format(" %s->%s = %s;", varname.Data(), membername.Data(), info->GetStrValue()) << std::endl;
446  break;
447  }
448  }
449 }
450 
452 {
453  return new TGo4ParameterStatus(this, kTRUE);
454 }
455 
457 {
458  return status ? status->UpdateParameterValues(this) : kFALSE;
459 }
TGo4ParameterStatus * CreateStatus()
void SetType(const char *name, Int_t id)
virtual ~TGo4Parameter()
virtual Int_t PrintParameter(Text_t *buffer=nullptr, Int_t buflen=0)
static void Info(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:294
Int_t FindArrayLength(TObjArray *items, Int_t &itemsindx, TDataMember *member)
void SavePrimitive(std::ostream &fs, Option_t *opt="") override
Bool_t UpdateParameterValues(TGo4Parameter *par)
const char * GetTypeName() const
void Clear(Option_t *opt="") override
Bool_t CheckArrayIndexes(Int_t ndim, Int_t indx1, Int_t indx2)
void Print(Option_t *opt="") const override
Bool_t UpdateFromUrl(const char *rest_url_opt)
void SetIntValue(Int_t value)
Bool_t SetMemberValues(TObjArray *fItems)
#define GO4TRACE(X)
Definition: TGo4Log.h:25
virtual Bool_t UpdateFrom(TGo4Parameter *rhs)
static void PrintLine(const char *text,...)
Definition: TGo4Status.cxx:101
void SetVisible(Bool_t on=kTRUE)
void SetMemberId(Int_t id)
void SetArrayIndexes(Int_t ndim=0, Int_t indx1=-1, Int_t indx2=-1)
Bool_t SetStatus(TGo4ParameterStatus *status)
void GetMemberValues(TObjArray *fItems)