Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:22:23

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             mCreationStatus = CreationStatus::Inserted;
0092         }
0093         else {
0094             ClearData();
0095             mData = aData;
0096             mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0097             mStatus = Status::Inserted;
0098             mCreationStatus = CreationStatus::Inserted;
0099         }
0100     }
0101 
0102     virtual void Set(std::vector<T*>&& aData) {
0103         ClearData();
0104         mData = std::move(aData);
0105         mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0106         mStatus = Status::Inserted;
0107         mCreationStatus = CreationStatus::Inserted;
0108     }
0109 
0110     virtual void Insert(T* aDatum) {
0111         mData.push_back(aDatum);
0112         mOutput.GetDatabundle().SetStatus(JDatabundle::Status::Inserted);
0113         mStatus = Status::Inserted;
0114         mCreationStatus = CreationStatus::Inserted;
0115     }
0116 
0117     /// Set a flag (or flags)
0118     inline void SetFactoryFlag(JFactory_Flags_t f) override {
0119         switch (f) {
0120             case JFactory::PERSISTENT: SetPersistentFlag(true); break;
0121             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(true); break;
0122             case JFactory::REGENERATE: SetRegenerateFlag(true); break;
0123             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(true); break;
0124             default: throw JException("Invalid factory flag");
0125         }
0126     }
0127 
0128     /// Clear a flag (or flags)
0129     inline void ClearFactoryFlag(JFactory_Flags_t f) {
0130         switch (f) {
0131             case JFactory::PERSISTENT: SetPersistentFlag(false); break;
0132             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(false); break;
0133             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0134             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0135             default: throw JException("Invalid factory flag");
0136         }
0137     }
0138 
0139     inline void SetNotOwnerFlag(bool not_owner) {
0140         mOutput.GetDatabundle().SetNotOwnerFlag(not_owner);
0141     }
0142 
0143 
0144     /// EnableGetAs generates a vtable entry so that users may extract the
0145     /// contents of this JFactoryT from the type-erased JFactory. The user has to manually specify which upcasts
0146     /// to allow, and they have to do so for each instance. It is recommended to do so in the constructor.
0147     /// Note that EnableGetAs<T>() is called automatically.
0148     template <typename S> void EnableGetAs ();
0149 
0150     // The following specializations allow automatically adding standard types (e.g. JObject) using things like
0151     // std::is_convertible(). The std::true_type version defers to the standard EnableGetAs().
0152     template <typename S> void EnableGetAs(std::true_type) { EnableGetAs<S>(); }
0153     template <typename S> void EnableGetAs(std::false_type) {}
0154 
0155 protected:
0156     std::vector<T*> mData;
0157     jana::components::Output<T> mOutput {this, &mData};
0158 };
0159 
0160 template<typename T>
0161 template<typename S>
0162 void JFactoryT<T>::EnableGetAs() {
0163 
0164     auto upcast_lambda = [this]() {
0165         std::vector<S*> results;
0166         for (auto t : mData) {
0167             results.push_back(static_cast<S*>(t));
0168         }
0169         return results;
0170     };
0171 
0172     auto key = std::type_index(typeid(S));
0173     using upcast_fn_t = std::function<std::vector<S*>()>;
0174     mUpcastVTable[key] = std::unique_ptr<JAny>(new JAnyT<upcast_fn_t>(std::move(upcast_lambda)));
0175 }
0176 
0177