ProjectionHandler Class Reference

#include <ProjectionHandler.hh>

Collaboration diagram for ProjectionHandler:

Collaboration graph
[legend]

List of all members.


Detailed Description

The projection handler is a central repository for projections to be used in a Rivet analysis run.

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< ProjHandleProjHandles
 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 ProjectionregisterProjection (const ProjectionApplier &parent, const Projection &proj, const string &name)
 Attach and retrieve a projection as a reference.
const ProjectionregisterProjection (const ProjectionApplier &parent, const Projection *proj, const string &name)
 Attach and retrieve a projection as a pointer.
Projection retrieval. */
const ProjectiongetProjection (const ProjectionApplier &parent, const string &name) const
set< const Projection * > getChildProjections (const ProjectionApplier &parent, ProjDepth depth=SHALLOW) const

Static Public Member Functions

static ProjectionHandlercreate ()
 Singleton creation function.
static void destroy ()
 Singleton deletion function.

Private Types

typedef map< const
ProjectionApplier
*, NamedProjs
NamedProjsMap

Private Member Functions

 ~ProjectionHandler ()
 Private destructor means no inheritance from this class.
ProjectionHandleroperator= (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).
LoggetLog () const
 Get a logger.
Construction. */
 ProjectionHandler ()
 The standard constructor.
Projection registration internal helpers
const Projection_getEquiv (const Projection &proj) const
const Projection_clone (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.

Member Typedef Documentation

typedef set<ProjHandle> ProjHandles

Typedef for a vector of Projection pointers.

Definition at line 49 of file ProjectionHandler.hh.

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.


Member Enumeration Documentation

enum ProjDepth

Enum to specify depth of projection search.

Enumerator:
SHALLOW 
DEEP 

Definition at line 56 of file ProjectionHandler.hh.

00056 { SHALLOW, DEEP };


Constructor & Destructor Documentation

~ProjectionHandler (  )  [private]

Private destructor means no inheritance from this class.

Definition at line 48 of file ProjectionHandler.cc.

References ProjectionHandler::clear().

00048                                         {
00049     clear();
00050   }

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().

00091 { }


Member Function Documentation

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   }

void destroy (  )  [static]

Singleton deletion function.

Definition at line 28 of file ProjectionHandler.cc.

References ProjectionHandler::_instance.

00028                                   {
00029     delete _instance;
00030   }

const Projection & registerProjection ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
)

Attach and retrieve a projection as a reference.

Definition at line 57 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().

00060   {
00061     getLog() << Log::TRACE << "Trying to register"
00062              << " projection " << &proj  << " (" << proj.name() << ")"
00063              << " for parent " << &parent << " (" << parent.name() << ")"
00064              << " with name '" << name << "'" << endl;
00065 
00066     // Check for duplicate use of "name" on "parent"
00067     const bool dupOk = _checkDuplicate(parent, proj, name);
00068     if (!dupOk) exit(1);
00069 
00070     // Choose which version of the projection to register with this parent and name
00071     const Projection* p = _getEquiv(proj);
00072     if (p == 0) { // a null pointer is a non-match
00073       // If there is no equivalent projection, clone proj and use the clone for registering
00074       p = _clone(proj);
00075     }
00076 
00077     // Do the registering
00078     p = _register(parent, *p, name);
00079 
00080     // Return registered proj
00081     return *p;
00082   }

const Projection * registerProjection ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
)

Attach and retrieve a projection as a pointer.

Definition at line 88 of file ProjectionHandler.cc.

References ProjectionHandler::registerProjection().

00090                                                                               {
00091     if (proj == 0) return 0;
00092     const Projection& p = registerProjection(parent, *proj, name);
00093     return &p;
00094   }

const Projection * _getEquiv ( const Projection proj  )  const [private]

Try to get an equivalent projection from the system

Returns:
0 if no equivalent projection found

Definition at line 146 of file ProjectionHandler.cc.

References ProjectionHandler::_projs, Rivet::EQUIVALENT, ProjectionHandler::getLog(), Projection::name(), Rivet::pcmp(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

00147   {
00148     // Get class type using RTTI
00149     const std::type_info& newtype = typeid(proj);
00150     getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl;
00151 
00152     // Compare to ALL projections via _projs collection
00153     getLog() << Log::TRACE << "Comparing " << &proj
00154              << " with " << _projs.size()
00155              << " registered projection" << (_projs.size() == 1 ? "" : "s") <<  endl;
00156     foreach (const ProjHandle& ph, _projs) {
00157       // Make sure the concrete types match, using RTTI.
00158       const std::type_info& regtype = typeid(*ph);
00159       getLog() << Log::TRACE << "RTTI type comparison with " << ph << ": "
00160                << newtype.name() << " vs. " << regtype.name() << endl;
00161       if (newtype != regtype) continue;
00162       getLog() << Log::TRACE << "RTTI type matches with " << ph << endl;
00163 
00164       // Test for semantic match
00165       if (pcmp(*ph, proj) != EQUIVALENT) {
00166         getLog() << Log::TRACE << "Projections at "
00167                  << &proj << " and " << ph << " are not equivalent" << endl;
00168       } else {
00169         getLog() << Log::TRACE << "MATCH! Projections at "
00170                  << &proj << " and " << ph << " are equivalent" << endl;
00171         return ph.get();
00172       }
00173     }
00174 
00175     // If no match, just return a null pointer
00176     return 0;
00177   }

const Projection * _clone ( const Projection proj  )  [private]

Make a clone of proj, copying across child references from the original.

Definition at line 99 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, Projection::clone(), ProjectionHandler::getLog(), Projection::name(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

00100   {
00101     // Clone a new copy of the passed projection on the heap
00102     getLog() << Log::TRACE << "Cloning projection " << proj.name() << " from " << &proj << endl;
00103     const Projection* newproj = proj.clone();
00104     getLog() << Log::TRACE << "Cloned projection " << proj.name() << " at " << newproj << endl;
00105     getLog() << Log::TRACE << "Clone types " << typeid(proj).name() << " -> " << typeid(newproj).name() << endl;
00106 
00107     // Copy all the child ProjHandles when cloning, since otherwise links to "stack parents"
00108     // will be generated by their children, without any connection to the cloned parent
00109     if (&proj != newproj) {
00110       NamedProjsMap::const_iterator nps = _namedprojs.find(&proj);
00111       if (nps != _namedprojs.end()) {
00112         getLog() << Log::TRACE << "Cloning registered projections list: "
00113                  << &proj << " -> " << newproj << endl;
00114         _namedprojs[newproj] = nps->second;
00115       }
00116     }
00117 
00118     return newproj;
00119   }

const Projection * _register ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
) [private]

Internal function to do the registering.

Definition at line 126 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, ProjectionHandler::getLog(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

00129   {
00130     ProjHandle ph(&proj);
00131     getLog() << Log::TRACE << "Registering new projection at " << ph << endl;
00132 
00133     // Add the passed Projection to _projs
00134     _projs.insert(ph);
00135 
00136     // Add the ProjApplier* => name location to the associative container
00137     _namedprojs[&parent][name] = ph;
00138 
00139     return ph.get();
00140   }

string _getStatus (  )  const [private]

Get a string dump of the current ProjHandler structure.

Definition at line 181 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionHandler::_checkDuplicate().

00181                                              {
00182     ostringstream msg;
00183     msg << "Current projection hierarchy:" << endl;
00184     foreach (const NamedProjsMap::value_type& nps, _namedprojs) {
00185       //const string parentname = nps.first->name();
00186       msg << nps.first << endl; //"(" << parentname << ")" << endl;
00187       foreach (const NamedProjs::value_type& np, nps.second) {
00188         msg << "  " << np.second << " (" << np.second->name()
00189             << ", locally called '" << np.first << "')" << endl;
00190       }
00191       msg << endl;
00192     }
00193     return msg.str();
00194   }

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 199 of file ProjectionHandler.cc.

References ProjectionHandler::_getStatus(), ProjectionHandler::_namedprojs, Log::ERROR, ProjectionHandler::getLog(), Projection::name(), and ProjectionApplier::name().

Referenced by ProjectionHandler::registerProjection().

00202   {
00203     NamedProjsMap::const_iterator ipnps = _namedprojs.find(&parent);
00204     if (ipnps != _namedprojs.end()) {
00205       const NamedProjs pnps = ipnps->second;
00206       const NamedProjs::const_iterator ipph = pnps.find(name);
00207       if (ipph != pnps.end()) {
00208         const ProjHandle pph = ipph->second;
00209         getLog() << Log::ERROR << "Projection clash! "
00210                  << parent.name() << " (" << &parent << ") "
00211                  << "is trying to overwrite its registered '" << name << "' "
00212                  << "projection (" << pph << "="
00213                  << pph->name() << ") with a non-equivalent projection "
00214                  << "(" << &proj << "=" << proj.name() << ")" << endl;
00215         getLog() << Log::ERROR << _getStatus();
00216         return false;
00217       }
00218     }
00219     return true;
00220   }

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 265 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionApplier::getProjection().

00266                                                                                {
00267     //getLog() << Log::TRACE << "Searching for child projection '"
00268     //         << name << "' of " << &parent << endl;
00269     NamedProjsMap::const_iterator nps = _namedprojs.find(&parent);
00270     if (nps == _namedprojs.end()) {
00271       ostringstream msg;
00272       msg << "No projections registered for parent " << &parent;
00273       throw Error(msg.str());
00274     }
00275     NamedProjs::const_iterator np = nps->second.find(name);
00276     if (np == nps->second.end()) {
00277       ostringstream msg;
00278       msg << "No projection '" << name << "' found for parent " << &parent;
00279       throw Error(msg.str());
00280     }
00281     // If it's registered with the projection handler, we must be able to safely
00282     // dereference the Projection pointer to a reference...
00283     return *(np->second);
00284   }

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 240 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::DEEP, and ProjectionHandler::SHALLOW.

Referenced by ProjectionApplier::getProjections().

00242   {
00243     set<const Projection*> toplevel;
00244     NamedProjs nps = _namedprojs.find(&parent)->second;
00245     foreach (NamedProjs::value_type& np, nps) {
00246       toplevel.insert(np.second.get());
00247     }
00248     if (depth == SHALLOW) {
00249       // Only return the projections directly contained within the top level
00250       return toplevel;
00251     } else {
00252       // Return recursively built projection list
00253       set<const Projection*> alllevels = toplevel;
00254       foreach (const Projection* p, toplevel) {
00255         set<const Projection*> allsublevels = getChildProjections(*p, DEEP);
00256         alllevels.insert(allsublevels.begin(), allsublevels.end());
00257       }
00258       return alllevels;
00259     }
00260   }

void clear (  ) 

Projection clearing method: deletes all known projections and empties the reference collections.

Definition at line 40 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, and ProjectionHandler::_projs.

Referenced by ProjectionHandler::~ProjectionHandler().

00040                                 {
00041     _projs.clear();
00042     _namedprojs.clear();
00043   }

void removeProjectionApplier ( ProjectionApplier parent  )  [private]

Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend).

Definition at line 225 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, and Rivet::pi.

Referenced by ProjectionApplier::~ProjectionApplier().

00225                                                                            {
00226     NamedProjsMap::iterator npi = _namedprojs.find(&parent);
00227     if (npi != _namedprojs.end()) _namedprojs.erase(npi);
00228     //
00229     const Projection* parentprojptr = dynamic_cast<Projection*>(&parent);
00230     if (parentprojptr) {
00231       ProjHandle parentph(parentprojptr);
00232       ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph);
00233       if (pi != _projs.end()) _projs.erase(pi);
00234     }
00235   }

Log & getLog (  )  const [private]

Get a logger.

Definition at line 34 of file ProjectionHandler.cc.

References Log::getLog().

Referenced by ProjectionHandler::_checkDuplicate(), ProjectionHandler::_clone(), ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), and ProjectionHandler::registerProjection().

00034                                        {
00035     return Log::getLog("Rivet.ProjectionHandler");
00036   }


Friends And Related Function Documentation

friend class ProjectionApplier [friend]

ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo.

Definition at line 46 of file ProjectionHandler.hh.


Member Data Documentation

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

Todo:
Threading?

Definition at line 96 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::create(), and ProjectionHandler::destroy().


The documentation for this class was generated from the following files: