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 #include <iterator>
0006 #include <iostream>
0007 #include <unistd.h>
0008 
0009 #include "JFactorySet.h"
0010 #include "JFactory.h"
0011 #include "JMultifactory.h"
0012 #include "JFactoryGenerator.h"
0013 
0014 //---------------------------------
0015 // JFactorySet    (Constructor)
0016 //---------------------------------
0017 JFactorySet::JFactorySet(void)
0018 {
0019 
0020 }
0021 
0022 //---------------------------------
0023 // JFactorySet    (Constructor)
0024 //---------------------------------
0025 JFactorySet::JFactorySet(const std::vector<JFactoryGenerator*>& generators)
0026 {
0027     // Add all factories from all factory generators
0028     for(auto generator : generators){
0029         generator->GenerateFactories(this);
0030     }
0031 }
0032 
0033 //---------------------------------
0034 // ~JFactorySet    (Destructor)
0035 //---------------------------------
0036 JFactorySet::~JFactorySet()
0037 {
0038     /// The destructor will delete any factories in the set, unless mIsFactoryOwner is set to false.
0039     /// The only time mIsFactoryOwner should/can be set false is when a JMultifactory is using a JFactorySet internally
0040     /// to manage its JMultifactoryHelpers.
0041     if (mIsFactoryOwner) {
0042 
0043         for (auto& pair : mDatabundlesFromUniqueName) {
0044             delete pair.second; // Databundles are always owned by the factoryset
0045         }
0046         for (auto& f : mFactories) delete f.second;
0047     }
0048     // Now that the factories are deleted, nothing can call the multifactories so it is safe to delete them as well
0049     for (auto* mf : mMultifactories) { delete mf; }
0050 }
0051 
0052 //---------------------------------
0053 // Add
0054 //---------------------------------
0055 void JFactorySet::Add(JDatabundle* databundle) {
0056 
0057     if (databundle->GetUniqueName().empty()) {
0058         throw JException("Attempted to add a databundle with no unique_name");
0059     }
0060     auto named_result = mDatabundlesFromUniqueName.find(databundle->GetUniqueName());
0061     if (named_result != std::end(mDatabundlesFromUniqueName)) {
0062         // Collection is duplicate. Since this almost certainly indicates a user error, and
0063         // the caller will not be able to do anything about it anyway, throw an exception.
0064         // We show the user which factory is causing this problem, including both plugin names
0065 
0066         auto ex = JException("Attempted to add duplicate databundles");
0067         ex.function_name = "JFactorySet::Add";
0068         ex.instance_name = databundle->GetUniqueName();
0069 
0070         auto fac = databundle->GetFactory();
0071         if (fac != nullptr) {
0072             ex.type_name = fac->GetTypeName();
0073             ex.plugin_name = fac->GetPluginName();
0074             if (named_result->second->GetFactory() != nullptr) {
0075                 ex.plugin_name += ", " + named_result->second->GetFactory()->GetPluginName();
0076             }
0077         }
0078         throw ex;
0079     }
0080     // Note that this is agnostic to event level. We may decide to change this.
0081     mDatabundlesFromUniqueName[databundle->GetUniqueName()] = databundle;
0082 }
0083 
0084 //---------------------------------
0085 // Add
0086 //---------------------------------
0087 bool JFactorySet::Add(JFactory* aFactory)
0088 {
0089     /// Add a JFactory to this JFactorySet. The JFactorySet assumes ownership of this factory.
0090     /// If the JFactorySet already contains a JFactory with the same key,
0091     /// throw an exception and let the user figure out what to do.
0092     /// This scenario occurs when the user has multiple JFactory<T> producing the
0093     /// same T JObject, and is not distinguishing between them via tags.
0094 
0095     auto typed_key = std::make_pair( aFactory->GetObjectType(), aFactory->GetTag() );
0096     auto untyped_key = std::make_pair( aFactory->GetObjectName(), aFactory->GetTag() );
0097 
0098     auto typed_result = mFactories.find(typed_key);
0099     auto untyped_result = mFactoriesFromString.find(untyped_key);
0100 
0101     if (typed_result != std::end(mFactories) || untyped_result != std::end(mFactoriesFromString)) {
0102         // Factory is duplicate. Since this almost certainly indicates a user error, and
0103         // the caller will not be able to do anything about it anyway, throw an exception.
0104         // We show the user which factory is causing this problem, including both plugin names
0105         std::string other_plugin_name;
0106         if (typed_result != std::end(mFactories)) {
0107             other_plugin_name = typed_result->second->GetPluginName();
0108         }
0109         else {
0110             other_plugin_name = untyped_result->second->GetPluginName();
0111         }
0112         auto ex = JException("Attempted to add duplicate factories");
0113         ex.function_name = "JFactorySet::Add";
0114         ex.instance_name = aFactory->GetPrefix();
0115         ex.type_name = aFactory->GetTypeName();
0116         ex.plugin_name = aFactory->GetPluginName() + ", " + other_plugin_name;
0117         throw ex;
0118     }
0119 
0120     mFactories[typed_key] = aFactory;
0121     mFactoriesFromString[untyped_key] = aFactory;
0122 
0123     for (auto* output : aFactory->GetDatabundleOutputs()) {
0124         for (const auto& bundle : output->GetDatabundles()) {
0125             bundle->SetFactory(aFactory);
0126             Add(bundle);
0127         }
0128     }
0129     return true;
0130 }
0131 
0132 
0133 bool JFactorySet::Add(JMultifactory *multifactory) {
0134     /// Add a JMultifactory to this JFactorySet. This JFactorySet takes ownership of its JMultifactoryHelpers,
0135     /// which was previously held by the JMultifactory.mHelpers JFactorySet.
0136     /// Ownership of the JMultifactory itself is shared among those helpers.
0137 
0138     auto helpers = multifactory->GetHelpers();
0139     for (auto fac : helpers->GetAllFactories()) {
0140         Add(fac);
0141     }
0142     helpers->mIsFactoryOwner = false;
0143     mMultifactories.push_back(multifactory);
0144     /// This is a little bit weird, but we are using a JFactorySet internally to JMultifactory in order to store and
0145     /// efficiently access its JMultifactoryHelpers. Ownership of the JMultifactoryHelpers is transferred to
0146     /// the enclosing JFactorySet.
0147     return true;
0148 }
0149 
0150 //---------------------------------
0151 // GetDataBundle
0152 //---------------------------------
0153 JDatabundle* JFactorySet::GetDatabundle(const std::string& unique_name) const {
0154     auto it = mDatabundlesFromUniqueName.find(unique_name);
0155     if (it != std::end(mDatabundlesFromUniqueName)) {
0156         auto fac = it->second->GetFactory();
0157         if (fac != nullptr && fac->GetLevel() != mLevel) {
0158             throw JException("Databundle belongs to a different level on the event hierarchy!");
0159         }
0160         return it->second;
0161     }
0162     return nullptr;
0163 }
0164 
0165 
0166 //---------------------------------
0167 // GetFactory
0168 //---------------------------------
0169 JFactory* JFactorySet::GetFactory(const std::string& object_name, const std::string& tag) const
0170 {
0171     auto untyped_key = std::make_pair(object_name, tag);
0172     auto it = mFactoriesFromString.find(untyped_key);
0173     if (it != std::end(mFactoriesFromString)) {
0174         if (it->second->GetLevel() != mLevel) {
0175             throw JException("Factory belongs to a different level on the event hierarchy!");
0176         }
0177         return it->second;
0178     }
0179     return nullptr;
0180 }
0181 
0182 //---------------------------------
0183 // GetAllFactories
0184 //---------------------------------
0185 std::vector<JFactory*> JFactorySet::GetAllFactories() const {
0186     std::vector<JFactory*> results;
0187     for (auto p : mFactories) {
0188         results.push_back(p.second);
0189     }
0190     return results;
0191 }
0192 
0193 //---------------------------------
0194 // GetAllMultifactories
0195 //---------------------------------
0196 std::vector<JMultifactory*> JFactorySet::GetAllMultifactories() const {
0197     std::vector<JMultifactory*> results;
0198     for (auto f : mMultifactories) {
0199         results.push_back(f);
0200     }
0201     return results;
0202 }
0203 
0204 //---------------------------------
0205 // GetAllDatabundleUniqueNames
0206 //---------------------------------
0207 std::vector<std::string> JFactorySet::GetAllDatabundleUniqueNames() const {
0208     std::vector<std::string> results;
0209     for (const auto& it : mDatabundlesFromUniqueName) {
0210         results.push_back(it.first);
0211     }
0212     return results;
0213 }
0214 
0215 //---------------------------------
0216 // Print
0217 //---------------------------------
0218 void JFactorySet::Print() const
0219 {
0220     size_t max_len = 0;
0221     for (auto p: mFactories) {
0222         if (p.second->GetLevel() != mLevel) continue;
0223         auto len = p.second->GetObjectName().length();
0224         if( len > max_len ) max_len = len;
0225     }
0226 
0227     max_len += 4;
0228     for (auto p: mFactories) {
0229         if (p.second->GetLevel() != mLevel) continue;
0230         auto name = p.second->GetObjectName();
0231         auto tag = p.second->GetTag();
0232 
0233         std::cout << std::string( max_len-name.length(), ' ') + name;
0234         if (!tag.empty()) std::cout << ":" << tag;
0235         std::cout << std::endl;
0236     }
0237 }
0238 
0239 //---------------------------------
0240 // Clear
0241 //---------------------------------
0242 void JFactorySet::Clear() {
0243 
0244     for (const auto& sFactoryPair : mFactories) {
0245         auto fac = sFactoryPair.second;
0246         fac->ClearData();
0247     }
0248     for (auto& it : mDatabundlesFromUniqueName) {
0249         // Clear any databundles that did not come from a JFactory
0250         if (it.second->GetFactory() == nullptr) {
0251             it.second->ClearData();
0252         }
0253     }
0254 }
0255 
0256 //---------------------------------
0257 // Finish
0258 //---------------------------------
0259 void JFactorySet::Finish() {
0260     for (auto& p : mFactories) {
0261         p.second->DoFinish();
0262     }
0263     for (auto& multifac : mMultifactories) {
0264         multifac->DoFinish();
0265     }
0266 }
0267