#include <ProjectionHandler.hh>
Without centralised projections, it can be hard to know which of an equivalent set of projections will be run on a particular event. In turn, this may mean that certain projections in the chain can go out of scope unexpectedly. There were originally also the issues that projections may need to be held as member pointers to an abstract base class, since post-construction setup is needed; that projections contained pointers to their own dependency chain, which could go out of scope; and that projection members could be modified after being applied to an event which, due to the caching model, would have unpredictable consequences.
By centralising all the projections, these issues are eliminated, as well as allowing analysis classes to contain fewer data members (since projections are now better accessed by name than by storing a data member reference or pointer).
The core of the ProjectionHandler design is that it is a singleton class, essentially a wrapper around a map of Projection*
, indexed by a hash of the registering object and its local name for the registered projection.
Definition at line 42 of file ProjectionHandler.hh.
Public Types | |
enum | ProjDepth { SHALLOW, DEEP } |
Enum to specify depth of projection search. More... | |
typedef set< ProjHandle > | ProjHandles |
Typedef for a vector of Projection pointers. | |
typedef map< const string, ProjHandle > | NamedProjs |
Typedef for the structure used to contain named projections for a particular containing Analysis or Projection. | |
Public Member Functions | |
void | clear () |
Projection registration | |
const Projection & | registerProjection (const ProjectionApplier &parent, const Projection &proj, const string &name) |
Attach and retrieve a projection as a reference. | |
const Projection * | registerProjection (const ProjectionApplier &parent, const Projection *proj, const string &name) |
Attach and retrieve a projection as a pointer. | |
Projection retrieval. */ | |
const Projection & | getProjection (const ProjectionApplier &parent, const string &name) const |
set< const Projection * > | getChildProjections (const ProjectionApplier &parent, ProjDepth depth=SHALLOW) const |
Static Public Member Functions | |
static ProjectionHandler * | create () |
Singleton creation function. | |
Private Types | |
typedef map< const ProjectionApplier *, NamedProjs > | NamedProjsMap |
Private Member Functions | |
~ProjectionHandler () | |
Private destructor means no inheritance from this class. | |
ProjectionHandler & | operator= (const ProjectionHandler &) |
The assignment operator is hidden. | |
ProjectionHandler (const ProjectionHandler &) | |
The copy constructor is hidden. | |
void | removeProjectionApplier (ProjectionApplier &parent) |
Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend). | |
Log & | getLog () const |
Get a logger. | |
Construction. */ | |
ProjectionHandler () | |
The standard constructor. | |
Projection registration internal helpers | |
const Projection * | _getEquiv (const Projection &proj) const |
const Projection * | _clone (const ProjectionApplier &parent, const Projection &proj) |
Make a clone of proj, copying across child references from the original. | |
const Projection * | _register (const ProjectionApplier &parent, const Projection &proj, const string &name) |
Internal function to do the registering. | |
string | _getStatus () const |
Get a string dump of the current ProjHandler structure. | |
bool | _checkDuplicate (const ProjectionApplier &parent, const Projection &proj, const string &name) const |
Check that this parent projection doesn't already use this name. | |
Private Attributes | |
NamedProjsMap | _namedprojs |
ProjHandles | _projs |
Static Private Attributes | |
static ProjectionHandler * | _instance = 0 |
Friends | |
class | ProjectionApplier |
ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo. |
typedef set<ProjHandle> ProjHandles |
typedef map<const string, ProjHandle> NamedProjs |
Typedef for the structure used to contain named projections for a particular containing Analysis or Projection.
Definition at line 53 of file ProjectionHandler.hh.
typedef map<const ProjectionApplier*, NamedProjs> NamedProjsMap [private] |
Structure used to map a containing Analysis or Projection to its set of contained projections.
Definition at line 63 of file ProjectionHandler.hh.
enum ProjDepth |
~ProjectionHandler | ( | ) | [private] |
Private destructor means no inheritance from this class.
Definition at line 44 of file ProjectionHandler.cc.
References ProjectionHandler::clear().
00044 { 00045 clear(); 00046 }
ProjectionHandler | ( | const ProjectionHandler & | ) | [private] |
The copy constructor is hidden.
ProjectionHandler | ( | ) | [inline, private] |
The standard constructor.
Definition at line 91 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::create().
ProjectionHandler& operator= | ( | const ProjectionHandler & | ) | [private] |
The assignment operator is hidden.
ProjectionHandler * create | ( | ) | [static] |
Singleton creation function.
Definition at line 18 of file ProjectionHandler.cc.
References ProjectionHandler::_instance, Log::getLog(), ProjectionHandler::ProjectionHandler(), and Log::TRACE.
00018 { 00019 if (!_instance) { 00020 _instance = new ProjectionHandler(); 00021 Log::getLog("Rivet.ProjectionHandler") 00022 << Log::TRACE << "Created new ProjectionHandler at " << _instance << endl; 00023 } 00024 return _instance; 00025 }
const Projection & registerProjection | ( | const ProjectionApplier & | parent, | |
const Projection & | proj, | |||
const string & | name | |||
) |
Attach and retrieve a projection as a reference.
Definition at line 53 of file ProjectionHandler.cc.
References ProjectionHandler::_checkDuplicate(), ProjectionHandler::_clone(), ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::getLog(), ProjectionApplier::name(), Projection::name(), and Log::TRACE.
Referenced by ProjectionApplier::_addProjection(), and ProjectionHandler::registerProjection().
00056 { 00057 getLog() << Log::TRACE << "Trying to register" 00058 << " projection " << &proj << " (" << proj.name() << ")" 00059 << " for parent " << &parent << " (" << parent.name() << ")" 00060 << " with name '" << name << "'" << endl; 00061 00062 // Check for duplicate use of "name" on "parent" 00063 const bool dupOk = _checkDuplicate(parent, proj, name); 00064 if (!dupOk) exit(1); 00065 00066 // Choose which version of the projection to register with this parent and name 00067 const Projection* p = _getEquiv(proj); 00068 if (p == 0) { // a null pointer is a non-match 00069 // If there is no equivalent projection, clone proj and use the clone for registering 00070 p = _clone(parent, proj); 00071 } 00072 00073 // Do the registering 00074 p = _register(parent, *p, name); 00075 00076 // Return registered proj 00077 return *p; 00078 }
const Projection * registerProjection | ( | const ProjectionApplier & | parent, | |
const Projection * | proj, | |||
const string & | name | |||
) |
Attach and retrieve a projection as a pointer.
Definition at line 84 of file ProjectionHandler.cc.
References ProjectionHandler::registerProjection().
00086 { 00087 if (proj == 0) return 0; 00088 const Projection& p = registerProjection(parent, *proj, name); 00089 return &p; 00090 }
const Projection * _getEquiv | ( | const Projection & | proj | ) | const [private] |
Try to get an equivalent projection from the system
Definition at line 143 of file ProjectionHandler.cc.
References ProjectionHandler::_projs, Rivet::EQUIVALENT, ProjectionHandler::getLog(), Projection::name(), Rivet::pcmp(), and Log::TRACE.
Referenced by ProjectionHandler::registerProjection().
00144 { 00145 // Get class type using RTTI 00146 const std::type_info& newtype = typeid(proj); 00147 getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl; 00148 00149 // Compare to ALL projections via _projs collection 00150 getLog() << Log::TRACE << "Comparing " << &proj 00151 << " with " << _projs.size() 00152 << " registered projection" << (_projs.size() == 1 ? "" : "s") << endl; 00153 foreach (const ProjHandle& ph, _projs) { 00154 // Make sure the concrete types match, using RTTI. 00155 const std::type_info& regtype = typeid(*ph); 00156 getLog() << Log::TRACE << "RTTI type comparison with " << ph << ": " 00157 << newtype.name() << " vs. " << regtype.name() << endl; 00158 if (newtype != regtype) continue; 00159 getLog() << Log::TRACE << "RTTI type matches with " << ph << endl; 00160 00161 // Test for semantic match 00162 if (pcmp(*ph, proj) != EQUIVALENT) { 00163 getLog() << Log::TRACE << "Projections at " 00164 << &proj << " and " << ph << " are not equivalent" << endl; 00165 } else { 00166 getLog() << Log::TRACE << "MATCH! Projections at " 00167 << &proj << " and " << ph << " are equivalent" << endl; 00168 return ph.get(); 00169 } 00170 } 00171 00172 // If no match, just return a null pointer 00173 return 0; 00174 }
const Projection* _clone | ( | const ProjectionApplier & | parent, | |
const Projection & | proj | |||
) | [private] |
Make a clone of proj, copying across child references from the original.
Referenced by ProjectionHandler::registerProjection().
const Projection * _register | ( | const ProjectionApplier & | parent, | |
const Projection & | proj, | |||
const string & | name | |||
) | [private] |
Internal function to do the registering.
Definition at line 123 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, ProjectionHandler::getLog(), and Log::TRACE.
Referenced by ProjectionHandler::registerProjection().
00126 { 00127 ProjHandle ph(&proj); 00128 getLog() << Log::TRACE << "Registering new projection at " << ph << endl; 00129 00130 // Add the passed Projection to _projs 00131 _projs.insert(ph); 00132 00133 // Add the ProjApplier* => name location to the associative container 00134 _namedprojs[&parent][name] = ph; 00135 00136 return ph.get(); 00137 }
string _getStatus | ( | ) | const [private] |
Get a string dump of the current ProjHandler structure.
Definition at line 178 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs.
Referenced by ProjectionHandler::_checkDuplicate().
00178 { 00179 ostringstream msg; 00180 msg << "Current projection hierarchy:" << endl; 00181 foreach (const NamedProjsMap::value_type& nps, _namedprojs) { 00182 //const string parentname = nps.first->name(); 00183 msg << nps.first << endl; //"(" << parentname << ")" << endl; 00184 foreach (const NamedProjs::value_type& np, nps.second) { 00185 msg << " " << np.second << " (" << np.second->name() 00186 << ", locally called '" << np.first << "')" << endl; 00187 } 00188 msg << endl; 00189 } 00190 return msg.str(); 00191 }
bool _checkDuplicate | ( | const ProjectionApplier & | parent, | |
const Projection & | proj, | |||
const string & | name | |||
) | const [private] |
Check that this parent projection doesn't already use this name.
Definition at line 196 of file ProjectionHandler.cc.
References ProjectionHandler::_getStatus(), ProjectionHandler::_namedprojs, Log::ERROR, ProjectionHandler::getLog(), Projection::name(), and ProjectionApplier::name().
Referenced by ProjectionHandler::registerProjection().
00199 { 00200 NamedProjsMap::const_iterator ipnps = _namedprojs.find(&parent); 00201 if (ipnps != _namedprojs.end()) { 00202 const NamedProjs pnps = ipnps->second; 00203 const NamedProjs::const_iterator ipph = pnps.find(name); 00204 if (ipph != pnps.end()) { 00205 const ProjHandle pph = ipph->second; 00206 getLog() << Log::ERROR << "Projection clash! " 00207 << parent.name() << " (" << &parent << ") " 00208 << "is trying to overwrite its registered '" << name << "' " 00209 << "projection (" << pph << "=" 00210 << pph->name() << ") with a non-equivalent projection " 00211 << "(" << &proj << "=" << proj.name() << ")" << endl; 00212 getLog() << Log::ERROR << _getStatus(); 00213 return false; 00214 } 00215 } 00216 return true; 00217 }
const Projection & getProjection | ( | const ProjectionApplier & | parent, | |
const string & | name | |||
) | const |
Retrieve a named projection for the given parent. Returning as a reference is partly to discourage ProjectionApplier classes from storing pointer members to the registered projections, since that can lead to problems and there is no need to do so.
Definition at line 262 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::getLog(), and Log::TRACE.
Referenced by ProjectionApplier::getProjection().
00263 { 00264 getLog() << Log::TRACE << "Searching for child projection '" 00265 << name << "' of " << &parent << endl; 00266 NamedProjsMap::const_iterator nps = _namedprojs.find(&parent); 00267 if (nps == _namedprojs.end()) { 00268 ostringstream msg; 00269 msg << "No projections registered for parent " << &parent; 00270 throw Error(msg.str()); 00271 } 00272 NamedProjs::const_iterator np = nps->second.find(name); 00273 if (np == nps->second.end()) { 00274 ostringstream msg; 00275 msg << "No projection '" << name << "' found for parent " << &parent; 00276 throw Error(msg.str()); 00277 } 00278 // If it's registered with the projection handler, we must be able to safely 00279 // dereference the Projection pointer to a reference... 00280 return *(np->second); 00281 }
set< const Projection * > getChildProjections | ( | const ProjectionApplier & | parent, | |
ProjDepth | depth = SHALLOW | |||
) | const |
Get child projections for the given parent. By default this will just return the projections directly contained by the parent, but the depth argument can be changed to do a deep retrieval, which will recurse through the whole projection chain. In this case, there is no protection against getting stuck in a circular projection dependency loop.
Definition at line 237 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::DEEP, and ProjectionHandler::SHALLOW.
Referenced by ProjectionApplier::getProjections().
00239 { 00240 set<const Projection*> toplevel; 00241 NamedProjs nps = _namedprojs.find(&parent)->second; 00242 foreach (NamedProjs::value_type& np, nps) { 00243 toplevel.insert(np.second.get()); 00244 } 00245 if (depth == SHALLOW) { 00246 // Only return the projections directly contained within the top level 00247 return toplevel; 00248 } else { 00249 // Return recursively built projection list 00250 set<const Projection*> alllevels = toplevel; 00251 foreach (const Projection* p, toplevel) { 00252 set<const Projection*> allsublevels = getChildProjections(*p, DEEP); 00253 alllevels.insert(allsublevels.begin(), allsublevels.end()); 00254 } 00255 return alllevels; 00256 } 00257 }
void clear | ( | ) |
Projection clearing method: deletes all known projections and empties the reference collections.
Definition at line 36 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, and ProjectionHandler::_projs.
Referenced by ProjectionHandler::~ProjectionHandler().
00036 { 00037 _projs.clear(); 00038 _namedprojs.clear(); 00039 }
void removeProjectionApplier | ( | ProjectionApplier & | parent | ) | [private] |
Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend).
Definition at line 222 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, and Rivet::pi.
Referenced by ProjectionApplier::~ProjectionApplier().
00222 { 00223 NamedProjsMap::iterator npi = _namedprojs.find(&parent); 00224 if (npi != _namedprojs.end()) _namedprojs.erase(npi); 00225 // 00226 const Projection* parentprojptr = dynamic_cast<Projection*>(&parent); 00227 if (parentprojptr) { 00228 ProjHandle parentph(parentprojptr); 00229 ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph); 00230 if (pi != _projs.end()) _projs.erase(pi); 00231 } 00232 }
Log & getLog | ( | ) | const [private] |
Get a logger.
Definition at line 30 of file ProjectionHandler.cc.
References Log::getLog().
Referenced by ProjectionHandler::_checkDuplicate(), ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::getProjection(), and ProjectionHandler::registerProjection().
00030 { 00031 return Log::getLog("Rivet.ProjectionHandler"); 00032 }
friend class ProjectionApplier [friend] |
ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo.
Definition at line 46 of file ProjectionHandler.hh.
NamedProjsMap _namedprojs [private] |
Core data member, associating a given containing class (via a ProjectionApplier pointer) to its contained projections.
Definition at line 67 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::_checkDuplicate(), ProjectionHandler::_getStatus(), ProjectionHandler::_register(), ProjectionHandler::clear(), ProjectionHandler::getChildProjections(), ProjectionHandler::getProjection(), and ProjectionHandler::removeProjectionApplier().
ProjHandles _projs [private] |
Cache of Projections for reverse lookup, to speed up registering new projections as _namedprojs
gets large.
Definition at line 71 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::clear(), and ProjectionHandler::removeProjectionApplier().
ProjectionHandler * _instance = 0 [static, private] |
Singleton instance
Definition at line 96 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::create().