Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-11 08:58:21

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/JHasInputs.h>
0013 #include <JANA/Components/JHasOutputs.h>
0014 #include <JANA/Components/JHasRunCallbacks.h>
0015 #include <JANA/JVersion.h>
0016 #if JANA2_HAVE_PODIO
0017 #include <JANA/Components/JPodioOutput.h>
0018 #endif
0019 #include <JANA/Components/JLightweightOutput.h>
0020 
0021 #include <string>
0022 #include <typeindex>
0023 #include <memory>
0024 #include <vector>
0025 
0026 
0027 class JEvent;
0028 class JObject;
0029 class JApplication;
0030 
0031 class JFactory : public jana::components::JComponent,
0032                  public jana::components::JHasRunCallbacks,
0033                  public jana::components::JHasInputs,
0034                  public jana::components::JHasOutputs {
0035 public:
0036 
0037     enum class InitStatus {InitNotRun, InitRun, InitExcepted};
0038     enum class CreationStatus { NotCreatedYet, Created };
0039     enum class Status {Empty, Processed, Inserted, Excepted};
0040 
0041     enum JFactory_Flags_t {
0042         JFACTORY_NULL = 0x00,    // Not used anywhere
0043         PERSISTENT = 0x01,       // Used heavily. Possibly better served by JServices, hierarchical events, or event groups. 
0044         WRITE_TO_OUTPUT = 0x02,  // Set in halld_recon but not read except by JANA1 janaroot and janacontrol plugins
0045         NOT_OBJECT_OWNER = 0x04, // Used heavily. Small conflict with PODIO subset collections, which do the same thing at a different level
0046         REGENERATE = 0x08        // Replaces JANA1 JFactory_base::use_factory and JFactory::GetCheckSourceFirst()
0047     };
0048 
0049     JFactory() {
0050         // Use CallbackStyle::ExpertMode any time we are NOT using JFactoryT
0051         // This retains backwards compatibility but also moves new code forward by default
0052         SetCallbackStyle(CallbackStyle::ExpertMode);
0053     }
0054     virtual ~JFactory() = default;
0055 
0056     void SetTag(std::string tag) {
0057         GetFirstDatabundle()->SetShortName(tag);
0058     }
0059 
0060     std::string GetTag() const { 
0061         auto db = GetFirstDatabundle();
0062         if (db->HasShortName()) {
0063             return db->GetShortName();
0064         }
0065         return db->GetUniqueName();
0066     }
0067 
0068     std::string GetObjectName() const { return mObjectName; }
0069 
0070     void SetObjectName(std::string object_name) { mObjectName = object_name; }
0071 
0072     std::string GetFactoryName() const { return m_type_name; }
0073     Status GetStatus() const { return mStatus; }
0074     InitStatus GetInitStatus() const { return mInitStatus; }
0075     [[deprecated]]
0076     CreationStatus GetCreationStatus() const { 
0077         if (mStatus == Status::Empty) return CreationStatus::NotCreatedYet;
0078         return CreationStatus::Created;
0079     }
0080     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.
0081 
0082     uint32_t GetPreviousRunNumber(void) const { return mPreviousRunNumber; }
0083 
0084     void SetFactoryName(std::string factoryName) { SetTypeName(factoryName); }
0085     void SetStatus(Status status){ mStatus = status; }
0086     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.
0087 
0088     void SetPreviousRunNumber(uint32_t aRunNumber) { mPreviousRunNumber = aRunNumber; }
0089 
0090     virtual void SetFactoryFlag(JFactory_Flags_t f) {
0091         switch (f) {
0092             case JFactory::PERSISTENT: SetPersistentFlag(true); break;
0093             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0094             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0095             default: throw JException("Unsupported factory flag");
0096         }
0097     };
0098 
0099     void SetPersistentFlag(bool persistent) { mPersistent = persistent; }
0100     void SetRegenerateFlag(bool regenerate) { mRegenerate = regenerate; }
0101     void SetWriteToOutputFlag(bool write_to_output) { mWriteToOutput = write_to_output; }
0102     bool GetWriteToOutputFlag() { return mWriteToOutput; }
0103 
0104     /// Get data source value depending on how objects came to be here. (Used mainly by JEvent::Get() )
0105     inline JCallGraphRecorder::JDataSource GetDataSource() const {
0106         JCallGraphRecorder::JDataSource datasource = JCallGraphRecorder::DATA_FROM_FACTORY;
0107         if( mStatus == JFactory::Status::Inserted ){
0108             if( m_insert_origin == JCallGraphRecorder::ORIGIN_FROM_SOURCE ){
0109                 datasource = JCallGraphRecorder::DATA_FROM_SOURCE;
0110             }else{
0111                 datasource = JCallGraphRecorder::DATA_FROM_CACHE; // Really came from factory, but if Inserted, it was a secondary data type.
0112             }
0113         }
0114         return datasource;
0115     }
0116 
0117     std::type_index GetObjectType() const {
0118         return GetFirstDatabundle()->GetTypeIndex();
0119     }
0120 
0121     std::size_t GetNumObjects() const {
0122         return GetFirstDatabundle()->GetSize();
0123     }
0124 
0125     void ClearData() {
0126 
0127         if (this->mStatus == JFactory::Status::Empty) {
0128             return;
0129         }
0130 
0131         if (mPersistent) {
0132             // Persistence is a property of both the factory AND the databundle
0133             // - "Don't re-run this factory on the next event"
0134             // - "Don't clear this databundle every time the JEvent gets recycled"
0135             // Factory is persistent <=> All databundles are persistent
0136             // We ARE allowing databundles to be persistent even if they don't have a JFactory
0137             // We don't have a way to enforce this generally yet
0138             return;
0139         }
0140 
0141         this->mStatus = JFactory::Status::Empty;
0142 
0143         for (auto* output: GetOutputs()) {
0144             output->ClearData();
0145         }
0146         for (auto* variadic_output : GetVariadicOutputs()) {
0147             variadic_output->ClearData();
0148         }
0149     }
0150 
0151 
0152     // Overloaded by user Factories
0153     virtual void Process(const std::shared_ptr<const JEvent>&) {}      // CallbackStyle::LegacyMode
0154     virtual void Process(const JEvent&) {}                             // CallbackStyle::ExpertMode
0155     virtual void Finish() {}
0156 
0157 
0158 
0159     /// Access the encapsulated data, performing an upcast if necessary. This is useful for extracting data from
0160     /// all JFactories<T> where T extends a parent class S, such as JObject or TObject, in contexts where T is not known
0161     /// or it would introduce an unwanted coupling. The main application is for building DSTs.
0162     ///
0163     /// Be aware of the following caveats:
0164     /// - The factory's object type must not use virtual inheritance.
0165     /// - If JFactory::Process hasn't already been called, this will return an empty vector. This will NOT call JFactory::Process.
0166     /// - Someone must call JFactoryT<T>::EnableGetAs<S>, preferably the constructor. Otherwise, this will return an empty vector.
0167     /// - If S isn't a base class of T, this will return an empty vector.
0168     template<typename S>
0169     std::vector<S*> GetAs();
0170 
0171 
0172 
0173     /// Create() calls JFactory::Init,BeginRun,Process in an invariant-preserving way without knowing the exact
0174     /// type of object contained. In order to access these objects when all you have is a JFactory*, use JFactory::GetAs().
0175     virtual void Create(const std::shared_ptr<const JEvent>& event);
0176     virtual void Create(const JEvent& event);
0177 
0178     void DoInit();
0179     void DoFinish();
0180     void Summarize(JComponentSummary& summary) const override;
0181 
0182     virtual void Set(const std::vector<JObject *>&) { throw JException("Not supported!"); }
0183 
0184 
0185 protected:
0186 
0187     bool mRegenerate = false;
0188     bool mWriteToOutput = true;
0189     bool mPersistent = false;
0190 
0191     int32_t mPreviousRunNumber = -1;
0192     bool mInsideCreate = false; // Use this to detect cycles in factory dependencies
0193     std::string mObjectName;
0194 
0195     Status mStatus = Status::Empty;
0196     InitStatus mInitStatus = InitStatus::InitNotRun;
0197     JCallGraphRecorder::JDataOrigin m_insert_origin = JCallGraphRecorder::ORIGIN_NOT_AVAILABLE; // (see note at top of JCallGraphRecorder.h)
0198     std::exception_ptr mException;
0199 };
0200 
0201 // We are moving away from JFactory::GetAs because it only considers the first databundle
0202 template<typename S>
0203 std::vector<S*> JFactory::GetAs() {
0204     return GetFirstDatabundle()->GetAs<S>();
0205 }
0206 
0207