Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-21 09:10:10

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       if (_projhandler != nullptr) {
0057         // If we have a registered proj handler, check its registered names for this PA
0058         return getProjHandler().hasProjection(*this, name);
0059       } else {
0060         // If we don't have a registered proj handler yet, check names against the queue
0061         for (const auto& ptr_name_pair : _declQueue) {
0062           if (ptr_name_pair.second == name) return true;
0063         }
0064         return false;
0065       }
0066     }
0067 
0068     /// Get the named projection, specifying return type via a template argument.
0069     /// @todo Add SFINAE to require that PROJ inherit from Projection
0070     template <typename PROJ>
0071     const PROJ& getProjection(const std::string& name) const {
0072       if (_projhandler != nullptr) {
0073         const Projection& p = getProjHandler().getProjection(*this, name);
0074         return pcast<PROJ>(p);
0075       }
0076       else {
0077         return getProjectionFromDeclQueue<PROJ>(name);
0078       }
0079     }
0080     /// Get the named projection, specifying return type via a template argument (user-facing alias).
0081     /// @todo Add SFINAE to require that PROJ inherit from Projection
0082     template <typename PROJ>
0083     const PROJ& get(const std::string& name) const { return getProjection<PROJ>(name); }
0084 
0085     /// Get the named projection (non-templated, so returns as a reference to a
0086     /// Projection base class).
0087     const Projection& getProjection(const std::string& name) const {
0088       return getProjHandler().getProjection(*this, name);
0089     }
0090 
0091     ///Get a named projection from this projection appliers declqueue
0092     ///TODO for TP: Recursion?
0093     template <typename PROJ>
0094     const PROJ& getProjectionFromDeclQueue(const std::string name) const {
0095       auto it = std::find_if(_declQueue.begin(), _declQueue.end(),
0096           [&name](const std::pair<std::shared_ptr<Projection>, std::string> &Qmember) {return Qmember.second == name;});
0097       if (it != _declQueue.end()){
0098         return dynamic_cast<PROJ&>(*(it->first));
0099       }
0100       else {
0101         //If projection isn't found, deal with it properly.
0102         MSG_ERROR("Projection " << name << " not found in declQueue of " << this << " (" << this->name() << ")");
0103         throw RangeError("Projection lookup failed in getProjectionFromDeclQueue");
0104       }
0105     }
0106     ///@}
0107 
0108 
0109     /// @name Projection applying functions
0110     /// @{
0111 
0112   public:
0113 
0114     /// Apply the supplied projection on event @a evt.
0115 
0116     /// Apply the supplied projection on event @a evt (user-facing alias).
0117     template <typename PROJ=Projection>
0118     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0119     apply(const Event& evt, const Projection& proj) const { return pcast<PROJ>(_apply(evt, proj)); }
0120 
0121     /// Apply the supplied projection on event @a evt (user-facing alias).
0122     template <typename PROJ=Projection>
0123     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0124     apply(const Event& evt, const PROJ& proj) const { return pcast<PROJ>(_apply(evt, proj)); }
0125 
0126     /// Apply the supplied projection on event @a evt (user-facing alias).
0127     template <typename PROJ=Projection>
0128     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0129     apply(const Event& evt, const std::string& name) const { return pcast<PROJ>(_apply(evt, name)); }
0130 
0131     /// Apply the supplied projection on event @a evt (convenience arg-reordering alias).
0132     template <typename PROJ=Projection>
0133     typename std::enable_if_t<std::is_base_of<Projection, PROJ>::value, const PROJ&>
0134     apply(const std::string& name, const Event& evt) const { return pcast<PROJ>(_apply(evt, name)); }
0135 
0136     /// @}
0137 
0138 
0139     /// Mark this object as owned by a proj-handler
0140     void markAsOwned() const { _owned = true; }
0141 
0142 
0143   protected:
0144 
0145     Log& getLog() const {
0146       return Log::getLog("Rivet.ProjectionHandler");
0147     }
0148 
0149 
0150     /// Get a reference to the ProjectionHandler for this thread.
0151     ProjectionHandler& getProjHandler() const {
0152       return *_projhandler;
0153     }
0154 
0155 
0156     private:
0157     /// @name Projection registration functions
0158     /// @{
0159 
0160     /// @brief Register a contained projection
0161     ///
0162     /// The type of the argument is used to instantiate a new projection
0163     /// internally: this new object is applied to events rather than the
0164     /// argument object. Hence you are advised to only use locally-scoped
0165     /// Projection objects in your Projection and Analysis constructors, and to
0166     /// avoid polymorphism (e.g. handling @c ConcreteProjection via a pointer or
0167     /// reference to type @c Projection) since this will screw up the internal
0168     /// type management.
0169     ///
0170     /// @todo Add SFINAE to require that PROJ inherit from Projection
0171     template <typename PROJ>
0172     const PROJ& declareProjection(const PROJ& proj, const std::string& name) const {
0173       const Projection& reg = _declareProjection(proj, name);
0174       const PROJ& rtn = dynamic_cast<const PROJ&>(reg);
0175       rtn.setProjectionHandler(getProjHandler());
0176       return rtn;
0177     }
0178 
0179     protected:
0180 
0181     /// @brief Register a contained projection (user-facing version)
0182     /// @todo Add SFINAE to require that PROJ inherit from Projection
0183     template <typename PROJ>
0184     const PROJ& declare(const PROJ& proj, const std::string& name) const {
0185       std::shared_ptr<Projection> projClone = proj.clone();
0186       _declQueue.push_back(make_pair(projClone, name));
0187       return (dynamic_cast<PROJ&>(*projClone));
0188    }
0189     /// @brief Register a contained projection (user-facing, arg-reordered version)
0190     /// @todo Add SFINAE to require that PROJ inherit from Projection
0191     template <typename PROJ>
0192     const PROJ& declare(const std::string& name, const PROJ& proj) const {
0193       std::shared_ptr<Projection> projClone = proj.clone();
0194       _declQueue.push_back(make_pair(projClone, name));
0195       return (dynamic_cast<PROJ&>(*projClone));
0196     }
0197 
0198 
0199     /// Untemplated function to do the work...
0200     const Projection& _declareProjection(const Projection& proj, const std::string& name) const;
0201 
0202     /// @}
0203 
0204 
0205     /// Non-templated version of string-based apply, to work around
0206     /// header dependency issue.
0207     const Projection& _apply(const Event& evt, const std::string& name) const;
0208 
0209     /// Non-templated version of proj-based apply, to work around
0210     /// header dependency issue.
0211     const Projection& _apply(const Event& evt, const Projection& proj) const;
0212 
0213 
0214     /// @todo AB: Add Doxygen comment, follow surrounding coding style
0215     void setProjectionHandler(ProjectionHandler& projectionHandler) const;
0216 
0217     /// Flag to forbid projection registration in analyses until the init phase
0218     bool _allowProjReg;
0219 
0220 
0221   private:
0222 
0223     /// Mark object as owned by the _projhandler
0224     mutable bool _owned;
0225 
0226     /// @brief Pointer to projection handler
0227     ///
0228     /// @todo TP: Would we prefer a smart pointer?
0229     mutable ProjectionHandler* _projhandler;
0230 
0231     /// @brief Queue storing child projections to be properly declared later
0232     ///
0233     /// Declaration receives reference to a Projection and a name, so we
0234     /// need to store both Projection and name for each queued child.
0235     mutable std::deque<pair<std::shared_ptr<Projection>, string>> _declQueue;
0236 
0237 protected:
0238 
0239     /// @brief Synchronise the declaration queue once a ProjectionHandler is attached
0240     ///
0241     /// If this applier is owned, recursively flush the declQueues of the
0242     /// child projections, registering _them_ to our projection handler.
0243     void _syncDeclQueue() const;
0244 
0245   };
0246 }
0247 
0248 #endif