ProjectionHandler Class Reference

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

#include <ProjectionHandler.hh>

Collaboration diagram for ProjectionHandler:
Collaboration graph
[legend]

List of all members.

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

Todo:
This is a better form of singleton, which cleans up properly... but it can't yet be used as it highlights a projection memory problem. Please fix so we can use this!
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 ProjectionHandlergetInstance ()
 Singleton creation function.

Private Types

typedef map< const
ProjectionApplier
*, NamedProjs
NamedProjsMap

Private Member Functions

void removeProjectionApplier (ProjectionApplier &parent)
 Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend).
LoggetLog () const
 Get a logger.
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

Friends

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

Construction. */



static ProjectionHandler_instance = 0
 ~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.
 ProjectionHandler ()
 The standard constructor.

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 41 of file ProjectionHandler.hh.


Member Typedef Documentation

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 52 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 62 of file ProjectionHandler.hh.

typedef set<ProjHandle> ProjHandles

Typedef for a vector of Projection pointers.

Definition at line 48 of file ProjectionHandler.hh.


Member Enumeration Documentation

enum ProjDepth

Enum to specify depth of projection search.

Enumerator:
SHALLOW 
DEEP 

Definition at line 55 of file ProjectionHandler.hh.

00055 { SHALLOW, DEEP };


Constructor & Destructor Documentation

~ProjectionHandler (  )  [private]

Private destructor means no inheritance from this class.

Definition at line 38 of file ProjectionHandler.cc.

References ProjectionHandler::clear().

00038                                         {
00039     clear();
00040   }

ProjectionHandler ( const ProjectionHandler  )  [private]

The copy constructor is hidden.

ProjectionHandler (  )  [inline, private]

The standard constructor.

Definition at line 88 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::getInstance().

00088 { }


Member Function Documentation

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

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

Referenced by ProjectionHandler::registerProjection().

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

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

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

Definition at line 92 of file ProjectionHandler.cc.

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

Referenced by ProjectionHandler::registerProjection().

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

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

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

Referenced by ProjectionHandler::registerProjection().

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

string _getStatus (  )  const [private]

Get a string dump of the current ProjHandler structure.

Definition at line 174 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionHandler::_checkDuplicate().

00174                                              {
00175     ostringstream msg;
00176     msg << "Current projection hierarchy:" << endl;
00177     foreach (const NamedProjsMap::value_type& nps, _namedprojs) {
00178       //const string parentname = nps.first->name();
00179       msg << nps.first << endl; //"(" << parentname << ")" << endl;
00180       foreach (const NamedProjs::value_type& np, nps.second) {
00181         msg << "  " << np.second << " (" << np.second->name()
00182             << ", locally called '" << np.first << "')" << endl;
00183       }
00184       msg << endl;
00185     }
00186     return msg.str();
00187   }

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

Internal function to do the registering.

Definition at line 119 of file ProjectionHandler.cc.

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

Referenced by ProjectionHandler::registerProjection().

00122   {
00123     ProjHandle ph(&proj);
00124     getLog() << Log::TRACE << "Registering new projection at " << ph << endl;
00125 
00126     // Add the passed Projection to _projs
00127     _projs.insert(ph);
00128 
00129     // Add the ProjApplier* => name location to the associative container
00130     _namedprojs[&parent][name] = ph;
00131 
00132     return ph.get();
00133   }

void clear (  ) 

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

Definition at line 31 of file ProjectionHandler.cc.

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

Referenced by ProjectionHandler::~ProjectionHandler().

00031                                 {
00032     _projs.clear();
00033     _namedprojs.clear();
00034   }

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

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

Referenced by ProjectionApplier::getProjections().

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

ProjectionHandler & getInstance (  )  [static]

Singleton creation function.

Definition at line 14 of file ProjectionHandler.cc.

References ProjectionHandler::_instance, ProjectionHandler::getLog(), ProjectionHandler::ProjectionHandler(), and Log::TRACE.

00014                                                     {
00015     if (!_instance) {
00016       _instance = new ProjectionHandler();
00017       Log::getLog("Rivet.ProjectionHandler")
00018         << Log::TRACE << "Created new ProjectionHandler at " << _instance << endl;
00019     }
00020     return *_instance;
00021   }

Log & getLog (  )  const [private]
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 258 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionApplier::getProjection().

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

ProjectionHandler& operator= ( const ProjectionHandler  )  [private]

The assignment operator is hidden.

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

Attach and retrieve a projection as a pointer.

Definition at line 81 of file ProjectionHandler.cc.

References ProjectionHandler::registerProjection().

00083                                                                               {
00084     if (proj == 0) return 0;
00085     const Projection& p = registerProjection(parent, *proj, name);
00086     return &p;
00087   }

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

Attach and retrieve a projection as a reference.

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

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

void removeProjectionApplier ( ProjectionApplier parent  )  [private]

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

Definition at line 218 of file ProjectionHandler.cc.

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

Referenced by ProjectionApplier::~ProjectionApplier().

00218                                                                            {
00219     NamedProjsMap::iterator npi = _namedprojs.find(&parent);
00220     if (npi != _namedprojs.end()) _namedprojs.erase(npi);
00221     //
00222     const Projection* parentprojptr = dynamic_cast<Projection*>(&parent);
00223     if (parentprojptr) {
00224       ProjHandle parentph(parentprojptr);
00225       ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph);
00226       if (pi != _projs.end()) _projs.erase(pi);
00227     }
00228   }


Friends And Related Function Documentation

friend class ProjectionApplier [friend]

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

Definition at line 45 of file ProjectionHandler.hh.


Member Data Documentation

ProjectionHandler * _instance = 0 [static, private]
Todo:
Remove in favour of the static singleton function

Definition at line 91 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::getInstance().

ProjHandles _projs [private]

Cache of Projections for reverse lookup, to speed up registering new projections as _namedprojs gets large.

Definition at line 70 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::clear(), and ProjectionHandler::removeProjectionApplier().


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