Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:57

0001 // -*- C++ -*-
0002 #ifndef RIVET_ProjectionApplier_HH
0003 #define RIVET_ProjectionApplier_HH
0004 
0005 #include <deque>
0006 #include "Rivet/Config/RivetCommon.hh"
0007 #include "Rivet/Projection.fhh"
0008 #include "Rivet/ProjectionHandler.hh"
0009 #include "Rivet/Tools/Logging.hh"
0010 
0011 namespace Rivet {
0012 
0013 
0014   // Forward declarations
0015   class Event;
0016 
0017 
0018   /// @brief Common base class for Projection and Analysis, used for internal polymorphism
0019   ///
0020   /// Empty interface used for storing Projection and Analysis pointers in the
0021   /// same container (used by the ProjectionHandler)
0022   class ProjectionApplier {
0023   public:
0024 
0025     // The proj handler needs access to reset the _allowProjReg flag before calling a.init()
0026     // friend class ProjectionHandler;
0027 
0028     /// Constructor
0029     ProjectionApplier();
0030 
0031     // Virtual destructor: ensure that inheritance is possible.
0032     virtual ~ProjectionApplier();
0033 
0034 
0035     /// @name Metadata functions
0036     /// @{
0037     /// Get the name of this Projection or Analysis class
0038     virtual std::string name() const = 0;
0039     /// @}
0040 
0041     /// @name Projection "getting" functions
0042     /// @{
0043 
0044     /// Get the contained projections, including recursion.
0045     std::set<ConstProjectionPtr> getProjections() const {
0046       return getProjHandler().getChildProjections(*this, ProjectionHandler::DEEP);
0047     }
0048 
0049     /// Get the contained projections, excluding recursion.
0050     std::set<ConstProjectionPtr> getImmediateChildProjections() const {
0051       return getProjHandler().getChildProjections(*this, ProjectionHandler::SHALLOW);
0052     }
0053 
0054     /// Does this applier have a projection registered under the name @a name?
0055     bool hasProjection(const std::string& name) const {
0056       return getProjHandler().hasProjection(*this, name);
0057     }
0058 
0059     /// Get the named projection, specifying return type via a template argument.
0060     /// @todo Add SFINAE to require that PROJ inherit from Projection
0061     template <typename PROJ>
0062     const PROJ& getProjection(const std::string& name) const {
0063       if (_projhandler != nullptr){
0064         const Projection& p = getProjHandler().getProjection(*this, name);
0065         return pcast<PROJ>(p);
0066       }
0067       else {
0068         return getProjectionFromDeclQueue<PROJ>(name);
0069       }
0070     }
0071     /// Get the named projection, specifying return type via a template argument (user-facing alias).
0072     /// @todo Add SFINAE to require that PROJ inherit from Projection
0073     template <typename PROJ>
0074     const PROJ& get(const std::string& name) const { return getProjection<PROJ>(name); }
0075 
0076     /// Get the named projection (non-templated, so returns as a reference to a
0077     /// Projection base class).
0078     const Projection& getProjection(const std::string& name) const {
0079       return getProjHandler().getProjection(*this, name);
0080     }
0081 
0082     ///Get a named projection from this projection appliers declqueue
0083     ///TODO for TP: Recursion?
0084     template <typename PROJ>
0085     const PROJ& getProjectionFromDeclQueue(const std::string name) const {
0086       auto it = std::find_if(_declQueue.begin(), _declQueue.end(),
0087           [&name](const std::pair<std::shared_ptr<Projection>, std::string> &Qmember) {return Qmember.second == name;});
0088       if (it != _declQueue.end()){
0089         return dynamic_cast<PROJ&>(*(it->first));
0090       }
0091       else {
0092         //If projection isn't found, deal with it properly.
0093         MSG_ERROR("Projection " << name << " not found in declQueue of " << this << " (" << this->name() << ")");
0094         throw RangeError("Projection lookup failed in getProjectionFromDeclQueue");
0095       }
0096     }
0097     ///@}
0098 
0099 
0100     /// @name Projection applying functions
0101     /// @{
0102 
0103   public:
0104 
0105     /// Apply the supplied projection on event @a evt.
0106 
0107     /// Apply the supplied projection on event @a evt (user-facing alias).
0108     template <typename PROJ=Projection>
0109     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0110     apply(const Event& evt, const Projection& proj) const { return pcast<PROJ>(_apply(evt, proj)); }
0111 
0112     /// Apply the supplied projection on event @a evt (user-facing alias).
0113     template <typename PROJ=Projection>
0114     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0115     apply(const Event& evt, const PROJ& proj) const { return pcast<PROJ>(_apply(evt, proj)); }
0116 
0117     /// Apply the supplied projection on event @a evt (user-facing alias).
0118     template <typename PROJ=Projection>
0119     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0120     apply(const Event& evt, const std::string& name) const { return pcast<PROJ>(_apply(evt, name)); }
0121 
0122     /// Apply the supplied projection on event @a evt (convenience arg-reordering alias).
0123     template <typename PROJ=Projection>
0124     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0125     apply(const std::string& name, const Event& evt) const { return pcast<PROJ>(_apply(evt, name)); }
0126 
0127     /// @}
0128 
0129 
0130     /// Mark this object as owned by a proj-handler
0131     void markAsOwned() const { _owned = true; }
0132 
0133 
0134   protected:
0135 
0136     Log& getLog() const {
0137       return Log::getLog("Rivet.ProjectionHandler");
0138     }
0139 
0140 
0141     /// Get a reference to the ProjectionHandler for this thread.
0142     ProjectionHandler& getProjHandler() const {
0143       return *_projhandler;
0144     }
0145 
0146 
0147     private:
0148     /// @name Projection registration functions
0149     /// @{
0150 
0151     /// @brief Register a contained projection
0152     ///
0153     /// The type of the argument is used to instantiate a new projection
0154     /// internally: this new object is applied to events rather than the
0155     /// argument object. Hence you are advised to only use locally-scoped
0156     /// Projection objects in your Projection and Analysis constructors, and to
0157     /// avoid polymorphism (e.g. handling @c ConcreteProjection via a pointer or
0158     /// reference to type @c Projection) since this will screw up the internal
0159     /// type management.
0160     ///
0161     /// @todo Add SFINAE to require that PROJ inherit from Projection
0162     template <typename PROJ>
0163     const PROJ& declareProjection(const PROJ& proj, const std::string& name) const {
0164       const Projection& reg = _declareProjection(proj, name);
0165       const PROJ& rtn = dynamic_cast<const PROJ&>(reg);
0166       rtn.setProjectionHandler(getProjHandler());
0167       return rtn;
0168     }
0169 
0170     protected:
0171 
0172     /// @brief Register a contained projection (user-facing version)
0173     /// @todo Add SFINAE to require that PROJ inherit from Projection
0174     template <typename PROJ>
0175     const PROJ& declare(const PROJ& proj, const std::string& name) const {
0176       std::shared_ptr<Projection> projClone = proj.clone();
0177       _declQueue.push_back(make_pair(projClone, name));
0178       return (dynamic_cast<PROJ&>(*projClone));
0179    }
0180     /// @brief Register a contained projection (user-facing, arg-reordered version)
0181     /// @todo Add SFINAE to require that PROJ inherit from Projection
0182     template <typename PROJ>
0183     const PROJ& declare(const std::string& name, const PROJ& proj) const {
0184       std::shared_ptr<Projection> projClone = proj.clone();
0185       _declQueue.push_back(make_pair(projClone, name));
0186       return (dynamic_cast<PROJ&>(*projClone));
0187     }
0188 
0189 
0190     /// Untemplated function to do the work...
0191     const Projection& _declareProjection(const Projection& proj, const std::string& name) const;
0192 
0193     /// @}
0194 
0195 
0196     /// Non-templated version of string-based apply, to work around
0197     /// header dependency issue.
0198     const Projection& _apply(const Event& evt, const std::string& name) const;
0199 
0200     /// Non-templated version of proj-based apply, to work around
0201     /// header dependency issue.
0202     const Projection& _apply(const Event& evt, const Projection& proj) const;
0203 
0204 
0205     /// @todo AB: Add Doxygen comment, follow surrounding coding style
0206     void setProjectionHandler(ProjectionHandler& projectionHandler) const;
0207 
0208     /// Flag to forbid projection registration in analyses until the init phase
0209     bool _allowProjReg;
0210 
0211 
0212   private:
0213 
0214     /// Mark object as owned by the _projhandler
0215     mutable bool _owned;
0216 
0217     /// Pointer to projection handler.
0218     /// @todo TP: Would we prefer a smart pointer?
0219     mutable ProjectionHandler* _projhandler;
0220     /// queue storing child projections that need to be properly declared later.
0221     /// Declare receives reference to a Projection and name, so we need to store both Projection and name.
0222     mutable std::deque<pair<std::shared_ptr<Projection>, string>> _declQueue;
0223 
0224 protected:
0225     /// If this applier is owned, recursively flush declQueues of child projections, registering them to the projhandler.
0226     void _syncDeclQueue() const;
0227 
0228   };
0229 }
0230 
0231 #endif