Jpp  19.1.0
the software that should make you happy
JManager.hh
Go to the documentation of this file.
1 #ifndef __JROOT__JMANAGER__
2 #define __JROOT__JMANAGER__
3 
4 #include <string>
5 #include <sstream>
6 #include <map>
7 
8 #include "TObject.h"
9 #include "TFile.h"
10 #include "TRegexp.h"
11 #include "TKey.h"
12 #include "TH1.h"
13 
14 #include "JLang/JException.hh"
15 #include "JLang/JPointer.hh"
16 #include "JLang/JManip.hh"
17 
18 #include "JROOT/JRootToolkit.hh"
19 
20 
21 /**
22  * \file
23  *
24  * Dynamic ROOT object management.
25  * \author mdejong
26  */
27 namespace JROOT {}
28 namespace JPP { using namespace JROOT; }
29 
30 namespace JROOT {
31 
32  using JLANG::JException;
33  using JLANG::JPointer;
34 
35 
36  /**
37  * Auxiliary class to manage set of compatible ROOT objects (e.g.\ histograms) using unique keys.\n
38  * For each use of the map operator <tt>[]</tt>, it is checked whether the corresponding client object exists.\n
39  * If the corresponding client object does not yet exists, a clone is made of the master object (i.e.\ the 'client').\n
40  * The name of the newly created object is derived from the name of the master object by replacing
41  * the wild card character with the value of the key according the optional format specifier.
42  */
43  template<class JKey_t, class JValue_t>
44  class JManager :
45  public JPointer<JValue_t>,
46  public std::map<JKey_t, JPointer<JValue_t>>
47  {
48  public:
49 
52 
53  /**
54  * Default constructor.
55  */
57  {}
58 
59 
60  /**
61  * Constructor.
62  *
63  * Note that the manager owns the master object pointed to.\n
64  * For saving the objects to file, use method JManager::Write
65  * (all objects are detached from the current ROOT directory).
66  *
67  * \param master master object
68  * \param wildcard wild card character
69  * \param format format specifier for replacement of wildcard character by value of key
70  */
71  JManager(JValue_t* master,
72  char wildcard = '%',
73  JFormat_t format = JFormat_t()) :
74  ptr_type(master),
75  map_type(),
76  wc (wildcard),
77  fmt(format)
78  {
79  using namespace std;
80  using namespace JPP;
81 
82  if (!this->is_valid()) {
83  THROW(JException, "No valid master");
84  }
85 
86  if (string(this->get()->GetName()).find(wc) == string::npos) {
87  THROW(JException, "Invalid wildcard <" << this->get()->GetName() << "> '" << wc << "'");
88  }
89 
90  detach(this->get());
91 
92  resetObject(this->get(), true);
93  }
94 
95 
96  /**
97  * Constructor.
98  *
99  * Note that the manager owns the master object pointed to.\n
100  * For saving the objects to file, use method JManager::Write
101  * (all objects are detached from the current ROOT directory).
102  *
103  * \param master master object
104  * \param name name of master
105  * \param wildcard wild card character
106  * \param format format specifier for replacement of wildcard character by value of key
107  */
108  JManager(JValue_t* master,
109  const std::string& name,
110  char wildcard = '%',
111  std::ios::fmtflags format = std::ios::fmtflags()) :
112  ptr_type(master),
113  map_type(),
114  wc (wildcard),
115  fmt(format)
116  {
117  using namespace std;
118  using namespace JPP;
119 
120  if (!this->is_valid()) {
121  THROW(JException, "No valid master");
122  }
123 
124  this->get()->SetName(name.c_str());
125 
126  if (string(this->get()->GetName()).find(wc) == string::npos) {
127  THROW(JException, "Invalid wildcard <" << this->get()->GetName() << "> '" << wc << "'");
128  }
129 
130  detach(this->get());
131 
132  resetObject(this->get(), true);
133  }
134 
135 
136  /**
137  * Copy constructor.
138  *
139  * Note that the master object of the given manager is cloned and the wildcard copied.\n
140  * The client objects are not copied.
141  *
142  * \param manager manager
143  */
144  JManager(const JManager& manager) :
145  ptr_type(NULL),
146  map_type(),
147  wc (manager.wc),
148  fmt(manager.fmt)
149  {
150  using namespace JPP;
151 
152  if (manager.is_valid()) {
153 
154  this->set((JValue_t*) manager.get()->Clone());
155 
156  detach(this->get());
157 
158  resetObject(this->get(), true);
159  }
160  }
161 
162 
163  /**
164  * Clear client objects.
165  */
166  void clear()
167  {
168  for (typename map_type::iterator i = this->begin(); i != this->end(); ++i) {
169  i->second.reset();
170  }
171 
172  this->clear();
173  }
174 
175 
176  /**
177  * Get pointer to object for given key.
178  *
179  * \param key key
180  * \return pointer to client object
181  */
182  JValue_t* operator[](JKey_t key)
183  {
184  using namespace std;
185  using namespace JPP;
186 
187  typename map_type::iterator i = this->find(key);
188 
189  if (i == this->end()) {
190 
191  string buffer = this->get()->GetName();
192  string::size_type ipos = buffer.find(wc);
193 
194  ostringstream os;
195 
196  fmt.put(os);
197 
198  os << key;
199 
200  buffer.replace(ipos, 1, os.str());
201 
202  JValue_t* p = (JValue_t*) this->get()->Clone(buffer.c_str());
203 
204  detach(p);
205 
206  resetObject(p, true);
207 
208  this->insert(make_pair(key,p));
209 
210  return p;
211 
212  } else {
213 
214  return i->second;
215  }
216  }
217 
218 
219  /**
220  * Read objects from file into manager.
221  *
222  * \param in input file or directory
223  * \param master master name
224  * \param wildcard wild card character
225  * \return manager
226  */
227  static JManager Read(TDirectory& in, const char* const master, const char wildcard)
228  {
229  using namespace std;
230  using namespace JPP;
231 
232  JManager manager;
233 
234  TString buffer = master;
235 
236  const Ssiz_t pos = buffer.Index(wildcard);
237 
238  const TString a = buffer(0, pos);
239  const TString b = buffer(pos+1, buffer.Length());
240 
241  buffer.ReplaceAll("[", "\\[");
242  buffer.ReplaceAll("]", "\\]");
243 
244  buffer.ReplaceAll(wildcard, ".*");
245 
246  const TRegexp regexp(buffer);
247 
248  TIter iter(in.GetListOfKeys());
249 
250  for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
251 
252  const TString tag(key->GetName());
253 
254  // option match
255 
256  if (tag.Index(regexp) != -1) {
257 
258  JValue_t* p = dynamic_cast<JValue_t*>(key->ReadObj());
259 
260  if (p != NULL) {
261 
262  detach(p);
263 
264  string buffer = p->GetName();
265 
266  if (a.Length() != 0) { buffer.replace(buffer.find(a), a.Length(), ""); }
267  if (b.Length() != 0) { buffer.replace(buffer.find(b), b.Length(), ""); }
268 
269  JKey_t key;
270 
271  istringstream(buffer) >> key;
272 
273  manager.insert(make_pair(key, p));
274  }
275  }
276  }
277 
278  return manager;
279  }
280 
281 
282  /**
283  * Read objects from file.
284  *
285  * \param in input file or directory
286  */
287  void Read(TDirectory& in)
288  {
289  if (this->is_valid()) {
290 
291  JManager buffer = Read(in, this->get()->GetName(), this->wc);
292 
293  this->swap(buffer);
294  }
295  }
296 
297 
298  /**
299  * Write objects to file.
300  *
301  * \param out output file or directory
302  * \param wm write master
303  */
304  void Write(TDirectory& out, const bool wm = false)
305  {
306  for (typename map_type::iterator i = this->begin(); i != this->end(); ++i) {
307  out.WriteTObject(i->second);
308  }
309 
310  if (wm) {
311  out.WriteTObject(this->get());
312  }
313  }
314 
315 
316  /**
317  * Write objects to file.
318  *
319  * \param file_name file name
320  * \param wm write master
321  */
322  void Write(const char* file_name, const bool wm = false)
323  {
324  TFile out(file_name, "RECREATE");
325 
326  this->Write(out, wm) ;
327 
328  out.Write();
329  out.Close();
330  }
331 
332 
333  /**
334  * Read manager from file.
335  *
336  * \param file file
337  * \param object manager
338  * \return file
339  */
340  inline friend TFile& operator>>(TFile& file, JManager& object)
341  {
342  object.Read(file);
343 
344  return file;
345  }
346 
347 
348  /**
349  * Write manager to file.
350  *
351  * \param file file
352  * \param object manager
353  * \return file
354  */
355  inline friend TFile& operator<<(TFile& file, JManager& object)
356  {
357  object.Write(file);
358 
359  return file;
360  }
361 
362  char wc;
364 
365  private:
366  /**
367  * Fall back for detaching object pointed to from ROOT I/O.
368  */
369  static void detach(...)
370  {}
371 
372 
373  /**
374  * Implementation for detaching of object pointed to from ROOT I/O.
375  *
376  * \param p pointer to object
377  */
378  static void detach(TH1* p)
379  {
380  if (p != NULL) {
381  p->SetDirectory(0);
382  }
383  }
384  };
385 
386 
387  /**
388  * Reset JManager object.
389  *
390  * \param object manager
391  * \param reset reset contents if true
392  */
393  template<class JKey_t, class JValue_t>
394  inline void resetObject(JManager<JKey_t, JValue_t>* object, const bool reset = false)
395  {
396  if (object->is_valid()) {
397 
398  resetObject(object->get(), reset);
399 
400  for (typename JManager<JKey_t, JValue_t>::iterator i = object->begin(); i != object->end(); ++i) {
401  resetObject(i->second.get(), reset);
402  }
403  }
404  }
405 }
406 
407 #endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
I/O manipulators.
bool is_valid() const
Check validity of pointer.
General exception.
Definition: JException.hh:24
Template implementation of class that holds pointer to object(s).
Definition: JPointer.hh:24
virtual JClass_t * get() const override
Get pointer.
Definition: JPointer.hh:64
virtual void set(JClass_t *p) override
Set pointer.
Definition: JPointer.hh:75
virtual void reset() override
Reset pointer.
Definition: JPointer.hh:84
Auxiliary class to manage set of compatible ROOT objects (e.g. histograms) using unique keys.
Definition: JManager.hh:47
JManager(const JManager &manager)
Copy constructor.
Definition: JManager.hh:144
static void detach(TH1 *p)
Implementation for detaching of object pointed to from ROOT I/O.
Definition: JManager.hh:378
void Read(TDirectory &in)
Read objects from file.
Definition: JManager.hh:287
JPointer< JValue_t > ptr_type
Definition: JManager.hh:50
static JManager Read(TDirectory &in, const char *const master, const char wildcard)
Read objects from file into manager.
Definition: JManager.hh:227
JManager(JValue_t *master, char wildcard='%', JFormat_t format=JFormat_t())
Constructor.
Definition: JManager.hh:71
friend TFile & operator>>(TFile &file, JManager &object)
Read manager from file.
Definition: JManager.hh:340
JValue_t * operator[](JKey_t key)
Get pointer to object for given key.
Definition: JManager.hh:182
std::map< JKey_t, ptr_type > map_type
Definition: JManager.hh:51
friend TFile & operator<<(TFile &file, JManager &object)
Write manager to file.
Definition: JManager.hh:355
JFormat_t fmt
Definition: JManager.hh:363
JManager()
Default constructor.
Definition: JManager.hh:56
void Write(TDirectory &out, const bool wm=false)
Write objects to file.
Definition: JManager.hh:304
JManager(JValue_t *master, const std::string &name, char wildcard='%', std::ios::fmtflags format=std::ios::fmtflags())
Constructor.
Definition: JManager.hh:108
void Write(const char *file_name, const bool wm=false)
Write objects to file.
Definition: JManager.hh:322
void clear()
Clear client objects.
Definition: JManager.hh:166
static void detach(...)
Fall back for detaching object pointed to from ROOT I/O.
Definition: JManager.hh:369
const double a
Definition: JQuadrature.cc:42
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary classes and methods for ROOT I/O.
void resetObject(JManager< JKey_t, JValue_t > *object, const bool reset=false)
Reset JManager object.
Definition: JManager.hh:394
Definition: JSTDTypes.hh:14
Data structure for format specifications.
Definition: JManip.hh:524
void put(std::ostream &out) const
Put format specificaton to given output stream.
Definition: JManip.hh:599