Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-07 08:56:22

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 <vector>
0008 #include <type_traits>
0009 
0010 #include <JANA/JApplication.h>
0011 #include <JANA/JFactory.h>
0012 #include <JANA/JObject.h>
0013 #include <JANA/JVersion.h>
0014 #include <JANA/Utils/JTypeInfo.h>
0015 #include <JANA/Components/JLightweightOutput.h>
0016 
0017 #if JANA2_HAVE_ROOT
0018 #include <TObject.h>
0019 #endif
0020 
0021 
0022 template<typename T>
0023 class JFactoryT : public JFactory {
0024 public:
0025 
0026     using IteratorType = typename std::vector<T*>::const_iterator;
0027     using PairType = std::pair<IteratorType, IteratorType>;
0028 
0029     JFactoryT(std::string tag="") {
0030         SetTag(tag);
0031         SetPrefix(mOutput.GetDatabundle().GetUniqueName());
0032         SetObjectName(mOutput.GetDatabundle().GetTypeName());
0033         SetTypeName(NAME_OF_THIS);
0034         SetCallbackStyle(CallbackStyle::LegacyMode);
0035 
0036         EnableGetAs<T>();
0037         EnableGetAs<JObject>( std::is_convertible<T,JObject>() ); // Automatically add JObject if this can be converted to it
0038 #if JANA2_HAVE_ROOT
0039         EnableGetAs<TObject>( std::is_convertible<T,TObject>() ); // Automatically add TObject if this can be converted to it
0040 #endif
0041     }
0042 
0043     ~JFactoryT() override = default;
0044 
0045     void Init() override {}
0046     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0047     void ChangeRun(const std::shared_ptr<const JEvent>&) override {}
0048     void EndRun() override {}
0049     void Process(const std::shared_ptr<const JEvent>&) override {}
0050 
0051 
0052     /// CreateAndGetData handles all the preconditions and postconditions involved in calling the user-defined Open(),
0053     /// ChangeRun(), and Process() methods. These include making sure the JFactory JApplication is set, Init() is called
0054     /// exactly once, exceptions are tagged with the originating plugin and eventsource, ChangeRun() is
0055     /// called if and only if the run number changes, etc.
0056     PairType CreateAndGetData(const std::shared_ptr<const JEvent>& event) {
0057         Create(*event.get());
0058         return std::make_pair(mData.cbegin(), mData.cend());
0059     }
0060 
0061     PairType CreateAndGetData(const JEvent& event) {
0062         Create(event);
0063         return std::make_pair(mData.cbegin(), mData.cend());
0064     }
0065 
0066     // Retrieve a const reference to the data directly (no copying!)
0067     const std::vector<T*>& GetData() {
0068         return mData;
0069     }
0070 
0071     /// Please use the typed setters instead whenever possible
0072     [[deprecated]]
0073     void Set(const std::vector<JObject*>& aData) override {
0074         std::vector<T*> data;
0075         for (auto obj : aData) {
0076             T* casted = dynamic_cast<T*>(obj);
0077             assert(casted != nullptr);
0078             data.push_back(casted);
0079         }
0080         Set(std::move(data));
0081     }
0082 
0083     virtual void Set(const std::vector<T*>& aData) {
0084         if (aData == mData) {
0085             // The user populated mData directly instead of populating a temporary vector and passing it to us.
0086             // Doing this breaks the JFactory::Status invariant unless they remember to call Set() afterwards.
0087             // Ideally, they would use a temporary vector and not access mData at all, but they are used to this
0088             // from JANA1 and I haven't found a cleaner solution that gives them what they want yet.
0089             mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0090             mStatus = Status::Inserted;
0091         }
0092         else {
0093             ClearData();
0094             mData = aData;
0095             mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0096             mStatus = Status::Inserted;
0097         }
0098     }
0099 
0100     virtual void Set(std::vector<T*>&& aData) {
0101         ClearData();
0102         mData = std::move(aData);
0103         mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0104         mStatus = Status::Inserted;
0105     }
0106 
0107     virtual void Insert(T* aDatum) {
0108         mData.push_back(aDatum);
0109         mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0110         mStatus = Status::Inserted;
0111     }
0112 
0113     /// Set a flag (or flags)
0114     inline void SetFactoryFlag(JFactory_Flags_t f) override {
0115         switch (f) {
0116             case JFactory::PERSISTENT: SetPersistentFlag(true); break;
0117             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(true); break;
0118             case JFactory::REGENERATE: SetRegenerateFlag(true); break;
0119             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(true); break;
0120             default: throw JException("Invalid factory flag");
0121         }
0122     }
0123 
0124     /// Clear a flag (or flags)
0125     inline void ClearFactoryFlag(JFactory_Flags_t f) {
0126         switch (f) {
0127             case JFactory::PERSISTENT: SetPersistentFlag(false); break;
0128             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(false); break;
0129             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0130             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0131             default: throw JException("Invalid factory flag");
0132         }
0133     }
0134 
0135     inline void SetNotOwnerFlag(bool not_owner) {
0136         mOutput.GetDatabundle().SetNotOwnerFlag(not_owner);
0137     }
0138 
0139 
0140     /// EnableGetAs generates a vtable entry so that users may extract the
0141     /// contents of this JFactoryT from the type-erased JFactory. The user has to manually specify which upcasts
0142     /// to allow, and they have to do so for each instance. It is recommended to do so in the constructor.
0143     /// Note that EnableGetAs<T>() is called automatically.
0144     template <typename S> void EnableGetAs ();
0145 
0146     // The following specializations allow automatically adding standard types (e.g. JObject) using things like
0147     // std::is_convertible(). The std::true_type version defers to the standard EnableGetAs().
0148     template <typename S> void EnableGetAs(std::true_type) { EnableGetAs<S>(); }
0149     template <typename S> void EnableGetAs(std::false_type) {}
0150 
0151 protected:
0152     std::vector<T*> mData;
0153     jana::components::Output<T> mOutput {this, &mData};
0154 };
0155 
0156 template<typename T>
0157 template<typename S>
0158 void JFactoryT<T>::EnableGetAs() {
0159     mOutput.GetDatabundle().template EnableGetAs<S>();
0160 }
0161 
0162