Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:51:34

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once 
0006 
0007 #include <JANA/JException.h>
0008 #include <JANA/Utils/JAny.h>
0009 #include <JANA/Utils/JEventLevel.h>
0010 #include <JANA/Utils/JCallGraphRecorder.h>
0011 #include <JANA/Components/JComponent.h>
0012 #include <JANA/Components/JHasDatabundleOutputs.h>
0013 
0014 #include <string>
0015 #include <typeindex>
0016 #include <memory>
0017 #include <vector>
0018 #include <unordered_map>
0019 #include <functional>
0020 
0021 
0022 class JEvent;
0023 class JObject;
0024 class JApplication;
0025 
0026 class JFactory : public jana::components::JComponent, 
0027                  public jana::components::JHasDatabundleOutputs {
0028 public:
0029 
0030     enum class Status {Uninitialized, Unprocessed, Processed, Inserted, Finished};
0031     enum class CreationStatus { NotCreatedYet, Created, Inserted, InsertedViaGetObjects, NeverCreated };
0032 
0033     enum JFactory_Flags_t {
0034         JFACTORY_NULL = 0x00,    // Not used anywhere
0035         PERSISTENT = 0x01,       // Used heavily. Possibly better served by JServices, hierarchical events, or event groups. 
0036         WRITE_TO_OUTPUT = 0x02,  // Set in halld_recon but not read except by JANA1 janaroot and janacontrol plugins
0037         NOT_OBJECT_OWNER = 0x04, // Used heavily. Small conflict with PODIO subset collections, which do the same thing at a different level
0038         REGENERATE = 0x08        // Replaces JANA1 JFactory_base::use_factory and JFactory::GetCheckSourceFirst()
0039     };
0040 
0041     JFactory() = default;
0042     virtual ~JFactory() = default;
0043 
0044     std::string GetTag() const { 
0045         auto& db = GetDatabundleOutputs().at(0)->GetDatabundles().at(0);
0046         if (db->HasShortName()) {
0047             return db->GetShortName();
0048         }
0049         return db->GetUniqueName();
0050     }
0051 
0052     std::string GetObjectName() const { return mObjectName; }
0053 
0054     void SetObjectName(std::string object_name) { mObjectName = object_name; }
0055 
0056     std::string GetFactoryName() const { return m_type_name; }
0057     Status GetStatus() const { return mStatus; }
0058     CreationStatus GetCreationStatus() const { return mCreationStatus; }
0059     JCallGraphRecorder::JDataOrigin GetInsertOrigin() const { return m_insert_origin; } ///< If objects were placed here by JEvent::Insert() this records whether that call was made from a source or factory.
0060 
0061     uint32_t GetPreviousRunNumber(void) const { return mPreviousRunNumber; }
0062 
0063     void SetFactoryName(std::string factoryName) { SetTypeName(factoryName); }
0064     void SetStatus(Status status){ mStatus = status; }
0065     void SetCreationStatus(CreationStatus status){ mCreationStatus = status; }
0066     void SetInsertOrigin(JCallGraphRecorder::JDataOrigin origin) { m_insert_origin = origin; } ///< Called automatically by JEvent::Insert() to records whether that call was made by a source or factory.
0067 
0068     void SetPreviousRunNumber(uint32_t aRunNumber) { mPreviousRunNumber = aRunNumber; }
0069 
0070     virtual void SetFactoryFlag(JFactory_Flags_t f) {
0071         switch (f) {
0072             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0073             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0074             default: throw JException("Unsupported factory flag");
0075         }
0076     };
0077     void SetRegenerateFlag(bool regenerate) { mRegenerate = regenerate; }
0078     void SetWriteToOutputFlag(bool write_to_output) { mWriteToOutput = write_to_output; }
0079     bool GetWriteToOutputFlag() { return mWriteToOutput; }
0080 
0081     /// Get data source value depending on how objects came to be here. (Used mainly by JEvent::Get() )
0082     inline JCallGraphRecorder::JDataSource GetDataSource() const {
0083         JCallGraphRecorder::JDataSource datasource = JCallGraphRecorder::DATA_FROM_FACTORY;
0084          if( mCreationStatus == JFactory::CreationStatus::Inserted ){
0085             if( m_insert_origin == JCallGraphRecorder::ORIGIN_FROM_SOURCE ){
0086                 datasource = JCallGraphRecorder::DATA_FROM_SOURCE;
0087             }else{
0088                 datasource = JCallGraphRecorder::DATA_FROM_CACHE; // Really came from factory, but if Inserted, it was a secondary data type.
0089             }
0090         }
0091         return datasource;
0092     }
0093 
0094     // Overloaded by JFactoryT
0095     virtual std::type_index GetObjectType() const = 0;
0096 
0097     virtual void ClearData() = 0;
0098 
0099 
0100     // Overloaded by user Factories
0101     virtual void Init() {}
0102     virtual void BeginRun(const std::shared_ptr<const JEvent>&) {}
0103     virtual void ChangeRun(const std::shared_ptr<const JEvent>&) {}
0104     virtual void EndRun() {}
0105     virtual void Process(const std::shared_ptr<const JEvent>&) {}
0106     virtual void Finish() {}
0107 
0108     virtual std::size_t GetNumObjects() const {
0109         return 0;
0110     }
0111 
0112 
0113     /// Access the encapsulated data, performing an upcast if necessary. This is useful for extracting data from
0114     /// all JFactories<T> where T extends a parent class S, such as JObject or TObject, in contexts where T is not known
0115     /// or it would introduce an unwanted coupling. The main application is for building DSTs.
0116     ///
0117     /// Be aware of the following caveats:
0118     /// - The factory's object type must not use virtual inheritance.
0119     /// - If JFactory::Process hasn't already been called, this will return an empty vector. This will NOT call JFactory::Process.
0120     /// - Someone must call JFactoryT<T>::EnableGetAs<S>, preferably the constructor. Otherwise, this will return an empty vector.
0121     /// - If S isn't a base class of T, this will return an empty vector.
0122     template<typename S>
0123     std::vector<S*> GetAs();
0124 
0125 
0126 
0127     /// Create() calls JFactory::Init,BeginRun,Process in an invariant-preserving way without knowing the exact
0128     /// type of object contained. In order to access these objects when all you have is a JFactory*, use JFactory::GetAs().
0129     virtual void Create(const std::shared_ptr<const JEvent>& event);
0130     virtual void Create(const JEvent& event);
0131 
0132     void DoInit();
0133     void DoFinish();
0134     void Summarize(JComponentSummary& summary) const override;
0135 
0136 
0137     virtual void Set(const std::vector<JObject *> &data) = 0;
0138     virtual void Insert(JObject *data) = 0;
0139 
0140 
0141 protected:
0142 
0143     bool mRegenerate = false;
0144     bool mWriteToOutput = true;
0145     int32_t mPreviousRunNumber = -1;
0146     bool mInsideCreate = false; // Use this to detect cycles in factory dependencies
0147     std::unordered_map<std::type_index, std::unique_ptr<JAny>> mUpcastVTable;
0148     std::string mObjectName;
0149 
0150     mutable Status mStatus = Status::Uninitialized;
0151     mutable JCallGraphRecorder::JDataOrigin m_insert_origin = JCallGraphRecorder::ORIGIN_NOT_AVAILABLE; // (see note at top of JCallGraphRecorder.h)
0152 
0153     CreationStatus mCreationStatus = CreationStatus::NotCreatedYet;
0154 };
0155 
0156 // Because C++ doesn't support templated virtual functions, we implement our own dispatch table, mUpcastVTable.
0157 // This means that the JFactoryT is forced to manually populate this table by calling JFactoryT<T>::EnableGetAs.
0158 // We have the option to make the vtable be a static member of JFactoryT<T>, but we have chosen not to because:
0159 //
0160 //   1. It would be inconsistent with the fact that the user is supposed to call EnableGetAs in the ctor
0161 //   2. People in the future may want to generalize GetAs to support user-defined S* -> T* conversions (which I don't recommend)
0162 //   3. The size of the vtable is expected to be very small (<10 elements, most likely 2)
0163 
0164 template<typename S>
0165 std::vector<S*> JFactory::GetAs() {
0166     std::vector<S*> results;
0167     auto ti = std::type_index(typeid(S));
0168     auto search = mUpcastVTable.find(ti);
0169     if (search != mUpcastVTable.end()) {
0170         using upcast_fn_t = std::function<std::vector<S*>()>;
0171         auto temp = static_cast<JAnyT<upcast_fn_t>*>(&(*search->second));
0172         upcast_fn_t upcast_fn = temp->t;
0173         results = upcast_fn();
0174     }
0175     return results;
0176 }
0177 
0178