Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:39

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 
0008 #include "JFactorySet.h"
0009 #include "JFactory.h"
0010 #include "JMultifactory.h"
0011 #include "JFactoryGenerator.h"
0012 
0013 //---------------------------------
0014 // JFactorySet    (Constructor)
0015 //---------------------------------
0016 JFactorySet::JFactorySet(void)
0017 {
0018 
0019 }
0020 
0021 //---------------------------------
0022 // JFactorySet    (Constructor)
0023 //---------------------------------
0024 JFactorySet::JFactorySet(const std::vector<JFactoryGenerator*>& generators)
0025 {
0026     // Add all factories from all factory generators
0027     for(auto generator : generators){
0028         generator->GenerateFactories(this);
0029     }
0030 }
0031 
0032 //---------------------------------
0033 // ~JFactorySet    (Destructor)
0034 //---------------------------------
0035 JFactorySet::~JFactorySet()
0036 {
0037     /// The destructor will delete any factories in the set, unless mIsFactoryOwner is set to false.
0038     /// The only time mIsFactoryOwner should/can be set false is when a JMultifactory is using a JFactorySet internally
0039     /// to manage its JMultifactoryHelpers.
0040     if (mIsFactoryOwner) {
0041         for (auto& f : mFactories) delete f.second;
0042     }
0043     // Now that the factories are deleted, nothing can call the multifactories so it is safe to delete them as well
0044     for (auto* mf : mMultifactories) { delete mf; }
0045 }
0046 
0047 //---------------------------------
0048 // Add
0049 //---------------------------------
0050 bool JFactorySet::Add(JFactory* aFactory)
0051 {
0052     /// Add a JFactory to this JFactorySet. The JFactorySet assumes ownership of this factory.
0053     /// If the JFactorySet already contains a JFactory with the same key,
0054     /// throw an exception and let the user figure out what to do.
0055     /// This scenario occurs when the user has multiple JFactory<T> producing the
0056     /// same T JObject, and is not distinguishing between them via tags.
0057 
0058     auto typed_key = std::make_pair( aFactory->GetObjectType(), aFactory->GetTag() );
0059     auto untyped_key = std::make_pair( aFactory->GetObjectName(), aFactory->GetTag() );
0060 
0061     auto typed_result = mFactories.find(typed_key);
0062     auto untyped_result = mFactoriesFromString.find(untyped_key);
0063 
0064     if (typed_result != std::end(mFactories) || untyped_result != std::end(mFactoriesFromString)) {
0065         // Factory is duplicate. Since this almost certainly indicates a user error, and
0066         // the caller will not be able to do anything about it anyway, throw an exception.
0067         // We show the user which factory is causing this problem, including both plugin names
0068         std::string other_plugin_name;
0069         if (typed_result != std::end(mFactories)) {
0070             other_plugin_name = typed_result->second->GetPluginName();
0071         }
0072         else {
0073             other_plugin_name = untyped_result->second->GetPluginName();
0074         }
0075         auto ex = JException("Attempted to add duplicate factories");
0076         ex.function_name = "JFactorySet::Add";
0077         ex.instance_name = aFactory->GetPrefix();
0078         ex.type_name = aFactory->GetTypeName();
0079         ex.plugin_name = aFactory->GetPluginName() + ", " + other_plugin_name;
0080         throw ex;
0081     }
0082 
0083     mFactories[typed_key] = aFactory;
0084     mFactoriesFromString[untyped_key] = aFactory;
0085     return true;
0086 }
0087 
0088 
0089 bool JFactorySet::Add(JMultifactory *multifactory) {
0090     /// Add a JMultifactory to this JFactorySet. This JFactorySet takes ownership of its JMultifactoryHelpers,
0091     /// which was previously held by the JMultifactory.mHelpers JFactorySet.
0092     /// Ownership of the JMultifactory itself is shared among those helpers.
0093 
0094     auto helpers = multifactory->GetHelpers();
0095     for (auto fac : helpers->GetAllFactories()) {
0096         Add(fac);
0097     }
0098     helpers->mIsFactoryOwner = false;
0099     mMultifactories.push_back(multifactory);
0100     /// This is a little bit weird, but we are using a JFactorySet internally to JMultifactory in order to store and
0101     /// efficiently access its JMultifactoryHelpers. Ownership of the JMultifactoryHelpers is transferred to
0102     /// the enclosing JFactorySet.
0103     return true;
0104 }
0105 
0106 //---------------------------------
0107 // GetFactory
0108 //---------------------------------
0109 JFactory* JFactorySet::GetFactory(const std::string& object_name, const std::string& tag) const
0110 {
0111     auto untyped_key = std::make_pair(object_name, tag);
0112     auto it = mFactoriesFromString.find(untyped_key);
0113     if (it != std::end(mFactoriesFromString)) {
0114         if (it->second->GetLevel() != mLevel) {
0115             throw JException("Factory belongs to a different level on the event hierarchy!");
0116         }
0117         return it->second;
0118     }
0119     return nullptr;
0120 }
0121 
0122 //---------------------------------
0123 // GetAllFactories
0124 //---------------------------------
0125 std::vector<JFactory*> JFactorySet::GetAllFactories() const {
0126     std::vector<JFactory*> results;
0127     for (auto p : mFactories) {
0128         results.push_back(p.second);
0129     }
0130     return results;
0131 }
0132 
0133 //---------------------------------
0134 // GetAllMultifactories
0135 //---------------------------------
0136 std::vector<JMultifactory*> JFactorySet::GetAllMultifactories() const {
0137     std::vector<JMultifactory*> results;
0138     for (auto f : mMultifactories) {
0139         results.push_back(f);
0140     }
0141     return results;
0142 }
0143 
0144 //---------------------------------
0145 // Print
0146 //---------------------------------
0147 void JFactorySet::Print() const
0148 {
0149     size_t max_len = 0;
0150     for (auto p: mFactories) {
0151         if (p.second->GetLevel() != mLevel) continue;
0152         auto len = p.second->GetObjectName().length();
0153         if( len > max_len ) max_len = len;
0154     }
0155 
0156     max_len += 4;
0157     for (auto p: mFactories) {
0158         if (p.second->GetLevel() != mLevel) continue;
0159         auto name = p.second->GetObjectName();
0160         auto tag = p.second->GetTag();
0161 
0162         std::cout << std::string( max_len-name.length(), ' ') + name;
0163         if (!tag.empty()) std::cout << ":" << tag;
0164         std::cout << std::endl;
0165     }
0166 }
0167 
0168 //---------------------------------
0169 // Clear
0170 //---------------------------------
0171 void JFactorySet::Clear() {
0172 
0173     for (const auto& sFactoryPair : mFactories) {
0174         auto sFactory = sFactoryPair.second;
0175         sFactory->ClearData();
0176         // This automatically clears multifactories because their data is stored in helper factories!
0177     }
0178 }
0179 
0180 //---------------------------------
0181 // Finish
0182 //---------------------------------
0183 void JFactorySet::Finish() {
0184     for (auto& p : mFactories) {
0185         p.second->DoFinish();
0186     }
0187     for (auto& multifac : mMultifactories) {
0188         multifac->DoFinish();
0189     }
0190 }
0191