#ifndef __JROOT__JMANAGER__ #define __JROOT__JMANAGER__ #include #include #include #include "TObject.h" #include "TFile.h" #include "TRegexp.h" #include "TKey.h" #include "JLang/JException.hh" #include "JLang/JPointer.hh" #include "JLang/JManip.hh" #include "JROOT/JRootToolkit.hh" /** * \file * * Dynamic ROOT object management. * \author mdejong */ namespace JROOT {} namespace JPP { using namespace JROOT; } namespace JROOT { using JLANG::JException; using JLANG::JPointer; /** * Auxiliary class to manage set of compatible ROOT objects (e.g.\ histograms) using unique keys.\n * For each use of the map operator [], it is checked whether the corresponding client object exists.\n * If the corresponding client object does not yet exists, a clone is made of the master object (i.e.\ the 'client').\n * The name of the newly created object is derived from the name of the master object by replacing * the wild card character with the value of the key according the optional format specifier. */ template class JManager : public JPointer, public std::map> { public: typedef JPointer ptr_type; typedef std::map map_type; /** * Default constructor. */ JManager() {} /** * Constructor. * * Note that the manager owns the master object pointed to.\n * For saving the objects to file, use method JManager::Write * (all objects are detached from the current ROOT directory). * * \param master master object * \param wildcard wild card character * \param format format specifier for replacement of wildcard character by value of key */ JManager(JValue_t* master, char wildcard = '%', JFormat_t format = JFormat_t()) : ptr_type(master), map_type(), wc (wildcard), fmt(format) { using namespace std; using namespace JPP; if (!this->is_valid()) { THROW(JException, "No valid master"); } if (string(this->get()->GetName()).find(wc) == string::npos) { THROW(JException, "Invalid wildcard <" << this->get()->GetName() << "> '" << wc << "'"); } resetObject(this->get(), true); } /** * Constructor. * * Note that the manager owns the master object pointed to.\n * For saving the objects to file, use method JManager::Write * (all objects are detached from the current ROOT directory). * * \param master master object * \param name name of master * \param wildcard wild card character * \param format format specifier for replacement of wildcard character by value of key */ JManager(JValue_t* master, const std::string& name, char wildcard = '%', std::ios::fmtflags format = std::ios::fmtflags()) : ptr_type(master), map_type(), wc (wildcard), fmt(format) { using namespace std; using namespace JPP; if (!this->is_valid()) { THROW(JException, "No valid master"); } this->get()->SetName(name.c_str()); if (string(this->get()->GetName()).find(wc) == string::npos) { THROW(JException, "Invalid wildcard <" << this->get()->GetName() << "> '" << wc << "'"); } resetObject(this->get(), true); } /** * Copy constructor. * * Note that the master object of the given manager is cloned and the wildcard copied.\n * The client objects are not copied. * * \param manager manager */ JManager(const JManager& manager) : ptr_type(NULL), map_type(), wc (manager.wc), fmt(manager.fmt) { using namespace JPP; if (manager.is_valid()) { this->set((JValue_t*) manager.get()->Clone()); resetObject(this->get(), true); } } /** * Clear client objects. */ void clear() { for (typename map_type::iterator i = this->begin(); i != this->end(); ++i) { i->second.reset(); } this->clear(); } /** * Get pointer to object for given key. * * \param key key * \return pointer to client object */ JValue_t* operator[](JKey_t key) { using namespace std; using namespace JPP; typename map_type::iterator i = this->find(key); if (i == this->end()) { string buffer = this->get()->GetName(); string::size_type ipos = buffer.find(wc); ostringstream os; fmt.put(os); os << key; buffer.replace(ipos, 1, os.str()); JValue_t* p = (JValue_t*) this->get()->Clone(buffer.c_str()); resetObject(p, true); this->insert(make_pair(key,p)); return p; } else { return i->second; } } /** * Read objects from file into manager. * * \param in input file or directory * \param master master name * \param wildcard wild card character * \return manager */ static JManager Read(TDirectory& in, const char* const master, const char wildcard) { using namespace std; using namespace JPP; JManager manager; TString buffer = master; const Ssiz_t pos = buffer.Index(wildcard); const TString a = buffer(0, pos); const TString b = buffer(pos+1, buffer.Length()); buffer.ReplaceAll("[", "\\["); buffer.ReplaceAll("]", "\\]"); buffer.ReplaceAll(wildcard, ".*"); const TRegexp regexp(buffer); TIter iter(in.GetListOfKeys()); for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) { const TString tag(key->GetName()); // option match if (tag.Index(regexp) != -1) { JValue_t* p = dynamic_cast(key->ReadObj()); if (p != NULL) { resetObject(p, false); string buffer = p->GetName(); if (a.Length() != 0) { buffer.replace(buffer.find(a), a.Length(), ""); } if (b.Length() != 0) { buffer.replace(buffer.find(b), b.Length(), ""); } JKey_t key; istringstream(buffer) >> key; manager.insert(make_pair(key, p)); } } } return manager; } /** * Read objects from file. * * \param in input file or directory */ void Read(TDirectory& in) { if (this->is_valid()) { JManager buffer = Read(in, this->get()->GetName(), this->wc); this->swap(buffer); } } /** * Write objects to file. * * \param out output file or directory * \param wm write master */ void Write(TDirectory& out, const bool wm = false) { for (typename map_type::iterator i = this->begin(); i != this->end(); ++i) { out.WriteTObject(i->second); } if (wm) { out.WriteTObject(this->get()); } } /** * Write objects to file. * * \param file_name file name * \param wm write master */ void Write(const char* file_name, const bool wm = false) { TFile out(file_name, "RECREATE"); this->Write(out, wm) ; out.Write(); out.Close(); } /** * Read manager from file. * * \param file file * \param object manager * \return file */ inline friend TFile& operator>>(TFile& file, JManager& object) { object.Read(file); return file; } /** * Write manager to file. * * \param file file * \param object manager * \return file */ inline friend TFile& operator<<(TFile& file, JManager& object) { object.Write(file); return file; } char wc; JFormat_t fmt; }; /** * Reset JManager object * * \param object manager * \param reset reset contents if true * \return true if successful; else false */ template inline bool resetObject(JManager* object, const bool reset = false) { if (object->is_valid()) { JROOT::resetObject(object->get(), reset); } for (typename JManager::iterator i = object->begin(); i != object->end(); ++i) { JROOT::resetObject(i->second.get(), reset); } return true; } } #endif