Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-13 08:28:03

0001 // Copyright 2024, Jefferson Science Associates, LLC.
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 // Created by Nathan Brei
0004 
0005 #pragma once
0006 #include "JANA/Components/JComponentSummary.h"
0007 #include <JANA/JVersion.h>
0008 #if JANA2_HAVE_PODIO
0009 #include "JANA/Components/JPodioDatabundle.h"
0010 #endif
0011 #include "JANA/Components/JLightweightDatabundle.h"
0012 #include "JANA/Utils/JEventLevel.h"
0013 #include "JANA/Utils/JTypeInfo.h"
0014 #include "JANA/JFactorySet.h"
0015 #include <typeindex>
0016 
0017 
0018 class JEvent;
0019 namespace jana::components {
0020 
0021 // Free function in order to break circular dependence on JEvent
0022 JFactorySet* GetFactorySetAtLevel(const JEvent& event, JEventLevel desired_level);
0023 void FactoryCreate(const JEvent& event, JFactory* factory);
0024 
0025 struct JHasInputs {
0026 
0027     class InputBase;
0028     class VariadicInputBase;
0029 
0030 protected:
0031 
0032     std::vector<InputBase*> m_inputs;
0033     std::vector<VariadicInputBase*> m_variadic_inputs;
0034     std::vector<std::pair<InputBase*, VariadicInputBase*>> m_ordered_inputs;
0035 
0036 public:
0037 
0038     void RegisterInput(InputBase* input) {
0039         m_inputs.push_back(input);
0040         m_ordered_inputs.push_back({input, nullptr});
0041     }
0042 
0043     void RegisterInput(VariadicInputBase* input) {
0044         m_variadic_inputs.push_back(input);
0045         m_ordered_inputs.push_back({nullptr, input});
0046     }
0047 
0048     const std::vector<InputBase*>& GetInputs() { 
0049         return m_inputs; 
0050     }
0051 
0052     const std::vector<VariadicInputBase*>& GetVariadicInputs() { 
0053         return m_variadic_inputs; 
0054     }
0055 
0056     struct InputOptions {
0057         std::string name {""};
0058         JEventLevel level {JEventLevel::None};
0059         bool is_optional {false};
0060     };
0061 
0062     struct VariadicInputOptions {
0063         std::vector<std::string> names {""};
0064         JEventLevel level {JEventLevel::None};
0065         bool is_optional {false};
0066     };
0067 
0068     class InputBase {
0069     protected:
0070         std::type_index m_type_index = std::type_index(typeid(JDatabundle::NoTypeProvided));
0071         std::string m_type_name;
0072         std::string m_databundle_name;
0073         JEventLevel m_level = JEventLevel::None;
0074         bool m_is_optional = false;
0075 
0076     public:
0077 
0078         virtual ~InputBase();
0079 
0080         void SetOptional(bool isOptional) {
0081             m_is_optional = isOptional;
0082         }
0083 
0084         void SetLevel(JEventLevel level) {
0085             m_level = level;
0086         }
0087 
0088         void SetDatabundleName(std::string name) {
0089             m_databundle_name = name;
0090         }
0091 
0092         const std::string& GetTypeName() const {
0093             return m_type_name;
0094         }
0095 
0096         const std::string& GetDatabundleName() const {
0097             return m_databundle_name;
0098         }
0099 
0100         JEventLevel GetLevel() const {
0101             return m_level;
0102         }
0103 
0104         void Configure(const InputOptions& options) {
0105             m_databundle_name = options.name;
0106             m_level = options.level;
0107             m_is_optional = options.is_optional;
0108         }
0109 
0110         void TriggerFactoryCreate(const JEvent& event);
0111         virtual void Populate(const JEvent& event) = 0;
0112     };
0113 
0114     class VariadicInputBase {
0115     public:
0116         enum class EmptyInputPolicy { IncludeNothing, IncludeEverything };
0117 
0118     protected:
0119         std::type_index m_type_index = std::type_index(typeid(JDatabundle::NoTypeProvided));
0120         std::string m_type_name;
0121         std::vector<std::string> m_requested_databundle_names;
0122         std::vector<std::string> m_realized_databundle_names;
0123         JEventLevel m_level = JEventLevel::None;
0124         bool m_is_optional = false;
0125         EmptyInputPolicy m_empty_input_policy = EmptyInputPolicy::IncludeNothing;
0126 
0127     public:
0128 
0129         virtual ~VariadicInputBase();
0130 
0131         void SetOptional(bool isOptional) {
0132             m_is_optional = isOptional;
0133         }
0134 
0135         void SetLevel(JEventLevel level) {
0136             m_level = level;
0137         }
0138 
0139         void SetRequestedDatabundleNames(std::vector<std::string> names) {
0140             m_requested_databundle_names = names;
0141             m_realized_databundle_names = names;
0142             // If options.names are empty, m_realized_databundle_names will be filled later
0143             // Otherwise, m_realized_databundle_names always matches m_requested_databundle_names
0144             // This weirdness is an optimization to avoid having to repopulate m_realized_databundle_names for every event
0145         }
0146 
0147         void SetEmptyInputPolicy(EmptyInputPolicy policy) {
0148             m_empty_input_policy = policy;
0149         }
0150 
0151         const std::string& GetTypeName() const {
0152             return m_type_name;
0153         }
0154 
0155         const std::vector<std::string>& GetRequestedDatabundleNames() const {
0156             return m_requested_databundle_names;
0157         }
0158 
0159         const std::vector<std::string>& GetRealizedDatabundleNames() const {
0160             return m_realized_databundle_names;
0161         }
0162 
0163         JEventLevel GetLevel() const {
0164             return m_level;
0165         }
0166 
0167         void Configure(const VariadicInputOptions& options) {
0168             m_requested_databundle_names = options.names;
0169             m_realized_databundle_names = options.names;
0170             // If options.names are empty, m_realized_databundle_names will be filled later
0171             // Otherwise, m_realized_databundle_names always matches m_requested_databundle_names
0172             // This weirdness is an optimization to avoid having to repopulate m_realized_databundle_names for every event
0173             m_level = options.level;
0174             m_is_optional = options.is_optional;
0175         }
0176 
0177         void TriggerFactoryCreate(const JEvent& event);
0178         virtual void Populate(const JEvent& event) = 0;
0179     };
0180 
0181 
0182     template <typename T>
0183     class Input : public InputBase {
0184 
0185         std::vector<const T*> m_data;
0186 
0187     public:
0188 
0189         Input(JHasInputs* owner) {
0190             owner->RegisterInput(this);
0191             m_type_index = std::type_index(typeid(T));
0192             m_type_name = JTypeInfo::demangle<T>();
0193             m_level = JEventLevel::None;
0194         }
0195 
0196         Input(JHasInputs* owner, const InputOptions& options) {
0197             owner->RegisterInput(this);
0198             m_type_index = std::type_index(typeid(T));
0199             m_type_name = JTypeInfo::demangle<T>();
0200             Configure(options);
0201         }
0202 
0203         void SetTag(std::string tag) {
0204             m_databundle_name = tag;
0205         }
0206 
0207         const std::vector<const T*>& operator()() { return m_data; }
0208         const std::vector<const T*>& operator*() { return m_data; }
0209         const std::vector<const T*>* operator->() { return &m_data; }
0210 
0211 
0212     private:
0213         friend class JComponentT;
0214 
0215         void Populate(const JEvent& event) {
0216 
0217             // Eventually, we might try maintaining a permanent link to the databundle
0218             // instead of having to retrieve it every time. This will only work if we are both on a
0219             // JFactory in the same JFactorySet, though.
0220 
0221             auto facset = GetFactorySetAtLevel(event, m_level);
0222             if (facset == nullptr) {
0223                 if (m_is_optional) {
0224                     return;
0225                 }
0226                 throw JException("Could not find parent at level=" + toString(m_level));
0227             }
0228             auto databundle = facset->GetDatabundle(std::type_index(typeid(T)), m_databundle_name);
0229             if (databundle == nullptr) {
0230                 if (!m_is_optional) {
0231                     facset->Print();
0232                     throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<T>() + " and tag=" + m_databundle_name);
0233                 }
0234                 m_data.clear();
0235                 return;
0236             };
0237             if (databundle->GetFactory() != nullptr) {
0238                 FactoryCreate(event, databundle->GetFactory());
0239             }
0240             auto* typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0241             if (typed_databundle == nullptr) {
0242                 if (!m_is_optional) {
0243                     facset->Print();
0244                     throw JException("Databundle with shortname '%s' does not inherit from JLightweightDatabundleT<%s>", m_databundle_name.c_str(), JTypeInfo::demangle<T>().c_str());
0245                 }
0246             }
0247             m_data.clear();
0248             m_data.insert(m_data.end(), typed_databundle->GetData().begin(), typed_databundle->GetData().end());
0249         }
0250     };
0251 
0252 #if JANA2_HAVE_PODIO
0253     template <typename PodioT>
0254     class PodioInput : public InputBase {
0255 
0256         const typename PodioT::collection_type* m_data;
0257 
0258     public:
0259 
0260         PodioInput(JHasInputs* owner) {
0261             owner->RegisterInput(this);
0262             m_type_index = std::type_index(typeid(PodioT));
0263             m_type_name = JTypeInfo::demangle<PodioT>();
0264             m_databundle_name = m_type_name;
0265             m_level = JEventLevel::None;
0266         }
0267 
0268         PodioInput(JHasInputs* owner, const InputOptions& options) {
0269             owner->RegisterInput(this);
0270             m_type_index = std::type_index(typeid(PodioT));
0271             m_type_name = JTypeInfo::demangle<PodioT>();
0272             m_databundle_name = m_type_name;
0273             Configure(options);
0274         }
0275 
0276         const typename PodioT::collection_type* operator()() {
0277             return m_data;
0278         }
0279         const typename PodioT::collection_type& operator*() {
0280             return *m_data;
0281         }
0282         const typename PodioT::collection_type* operator->() {
0283             return m_data;
0284         }
0285 
0286         void SetCollectionName(std::string name) {
0287             m_databundle_name = name;
0288         }
0289 
0290         void SetTag(std::string tag) {
0291             m_databundle_name = m_type_name + ":" + tag;
0292         }
0293 
0294         void Populate(const JEvent& event) {
0295             auto facset = GetFactorySetAtLevel(event, m_level);
0296             if (facset == nullptr) {
0297                 if (m_is_optional) {
0298                     return;
0299                 }
0300                 throw JException("Could not find parent at level=" + toString(m_level));
0301             }
0302             auto databundle = facset->GetDatabundle(std::type_index(typeid(PodioT)), m_databundle_name);
0303             if (databundle == nullptr) {
0304                 if (!m_is_optional) {
0305                     facset->Print();
0306                     throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<PodioT>() + " and tag=" + m_databundle_name);
0307                 }
0308                 // data IS optional, so we exit
0309                 m_data = nullptr;
0310                 return;
0311             };
0312             if (databundle->GetFactory() != nullptr) {
0313                 FactoryCreate(event, databundle->GetFactory());
0314             }
0315             auto* typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0316             if (typed_databundle == nullptr) {
0317                 facset->Print();
0318                 throw JException("Databundle with unique name '%s' does not inherit from JPodioDatabundle", databundle->GetUniqueName().c_str());
0319             }
0320             m_data = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0321             if (m_data == nullptr) {
0322                 throw JException("Databundle with unique name '%s' does not contain %s", databundle->GetUniqueName().c_str(), JTypeInfo::demangle<typename PodioT::collection_type>().c_str());
0323             }
0324         }
0325     };
0326 #endif
0327 
0328 
0329     template <typename T>
0330     class VariadicInput : public VariadicInputBase {
0331 
0332         std::vector<std::vector<const T*>> m_datas;
0333 
0334     public:
0335 
0336         VariadicInput(JHasInputs* owner) {
0337             owner->RegisterInput(this);
0338             m_type_index = std::type_index(typeid(T));
0339             m_type_name = JTypeInfo::demangle<T>();
0340             m_level = JEventLevel::None;
0341         }
0342 
0343         VariadicInput(JHasInputs* owner, const VariadicInputOptions& options) {
0344             owner->RegisterInput(this);
0345             m_type_index = std::type_index(typeid(T));
0346             m_type_name = JTypeInfo::demangle<T>();
0347             Configure(options);
0348         }
0349 
0350         void SetTags(std::vector<std::string> tags) {
0351             m_requested_databundle_names = tags;
0352             m_realized_databundle_names = tags;
0353         }
0354 
0355         const std::vector<std::vector<const T*>>& operator()() { return m_datas; }
0356         const std::vector<std::vector<const T*>>& operator*() { return m_datas; }
0357         const std::vector<std::vector<const T*>>* operator->() { return &m_datas; }
0358 
0359         const std::vector<const T*>& operator()(size_t index) { return m_datas.at(index); }
0360 
0361 
0362     private:
0363         friend class JComponentT;
0364 
0365         void Populate(const JEvent& event) {
0366             m_datas.clear();
0367             auto facset = GetFactorySetAtLevel(event, m_level);
0368             if (facset == nullptr) {
0369                 if (m_is_optional) {
0370                     return;
0371                 }
0372                 throw JException("Could not find parent at level=" + toString(m_level));
0373             }
0374             if (!m_requested_databundle_names.empty()) {
0375                 // We have a nonempty input, so we provide the user exactly the inputs they asked for (some of these may be null IF is_optional=true)
0376                 for (auto& short_or_unique_name : m_requested_databundle_names) {
0377                     auto databundle = facset->GetDatabundle(std::type_index(typeid(T)), short_or_unique_name);
0378                     if (databundle == nullptr) {
0379                         if (!m_is_optional) {
0380                             facset->Print();
0381                             throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<T>() + " and name=" + short_or_unique_name);
0382                         }
0383                         m_datas.push_back({}); // If a databundle is optional and missing, we still insert an empty vector for it
0384                         continue;
0385                     };
0386                     if (databundle->GetFactory() != nullptr) {
0387                         FactoryCreate(event, databundle->GetFactory());
0388                     }
0389                     auto* typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0390                     if (typed_databundle == nullptr) {
0391                         facset->Print();
0392                         throw JException("Databundle with shortname '%s' does not inherit from JLightweightDatabundleT<%s>", short_or_unique_name.c_str(), JTypeInfo::demangle<T>().c_str());
0393                     }
0394                     m_datas.push_back({});
0395                     auto& dest = m_datas.back();
0396                     dest.insert(dest.end(), typed_databundle->GetData().begin(), typed_databundle->GetData().end());
0397                 }
0398             }
0399             else if (m_empty_input_policy == EmptyInputPolicy::IncludeEverything) {
0400                 // We have an empty input and a nontrivial empty input policy
0401                 m_realized_databundle_names.clear();
0402 
0403                 auto databundles = facset->GetDatabundles(std::type_index(typeid(T)));
0404                 for (auto* databundle : databundles) {
0405 
0406                     auto typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0407                     if (typed_databundle == nullptr) {
0408                         throw JException("Databundle with name=" + typed_databundle->GetUniqueName() + " does not inherit from JLightweightDatabundleT<" + JTypeInfo::demangle<T>() + ">");
0409                     }
0410                     auto& contents = typed_databundle->GetData();
0411                     m_datas.push_back({}); // Create a destination for this factory's data
0412                     auto& dest = m_datas.back();
0413                     dest.insert(dest.end(), contents.begin(), contents.end());
0414                     if (databundle->HasShortName()) {
0415                         m_realized_databundle_names.push_back(databundle->GetShortName());
0416                     }
0417                     else {
0418                         m_realized_databundle_names.push_back(databundle->GetUniqueName());
0419                     }
0420                 }
0421             }
0422         }
0423     };
0424 
0425 
0426 
0427 #if JANA2_HAVE_PODIO
0428     template <typename PodioT>
0429     class VariadicPodioInput : public VariadicInputBase {
0430 
0431         std::vector<const typename PodioT::collection_type*> m_datas;
0432 
0433     public:
0434 
0435         VariadicPodioInput(JHasInputs* owner) {
0436             owner->RegisterInput(this);
0437             m_type_index = std::type_index(typeid(PodioT));
0438             m_type_name = JTypeInfo::demangle<PodioT>();
0439         }
0440 
0441         VariadicPodioInput(JHasInputs* owner, const VariadicInputOptions& options) {
0442             owner->RegisterInput(this);
0443             m_type_index = std::type_index(typeid(PodioT));
0444             m_type_name = JTypeInfo::demangle<PodioT>();
0445             Configure(options);
0446         }
0447 
0448         const std::vector<const typename PodioT::collection_type*> operator()() {
0449             return m_datas;
0450         }
0451 
0452         void SetRequestedCollectionNames(std::vector<std::string> names) {
0453             m_requested_databundle_names = names;
0454             m_realized_databundle_names = std::move(names);
0455         }
0456 
0457         const std::vector<std::string>& GetRealizedCollectionNames() {
0458             return GetRealizedDatabundleNames();
0459         }
0460 
0461         void Populate(const JEvent& event) {
0462             auto facset = GetFactorySetAtLevel(event, m_level);
0463             if (facset == nullptr) {
0464                 if (m_is_optional) {
0465                     return;
0466                 }
0467                 throw JException("Could not find parent at level=" + toString(m_level));
0468             }
0469             bool need_dynamic_realized_databundle_names = (m_requested_databundle_names.empty()) && (m_empty_input_policy != EmptyInputPolicy::IncludeNothing);
0470             if (need_dynamic_realized_databundle_names) {
0471                 m_realized_databundle_names.clear();
0472             }
0473             m_datas.clear();
0474             if (!m_requested_databundle_names.empty()) {
0475                 for (auto& short_or_unique_name : m_requested_databundle_names) {
0476                     auto databundle = facset->GetDatabundle(std::type_index(typeid(PodioT)), short_or_unique_name);
0477                     if (databundle == nullptr) {
0478                         if (!m_is_optional) {
0479                             facset->Print();
0480                             throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<PodioT>() + " and name=" + short_or_unique_name);
0481                         }
0482                         m_datas.push_back(nullptr);
0483                         continue;
0484                     }
0485                     if (databundle->GetFactory() != nullptr) {
0486                         FactoryCreate(event, databundle->GetFactory());
0487                     }
0488                     auto* typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0489                     if (typed_databundle == nullptr) {
0490                         facset->Print();
0491                         throw JException("Databundle with name '%s' does not inherit from JPodioDatabundle", short_or_unique_name.c_str());
0492                     }
0493                     auto* typed_collection = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0494                     if (typed_collection == nullptr) {
0495                         throw JException("Databundle with unique name '%s' does not contain %s", short_or_unique_name.c_str(), JTypeInfo::demangle<typename PodioT::collection_type>().c_str());
0496                     }
0497 
0498                     m_datas.push_back(typed_collection); // This MIGHT be nullptr if m_is_optional==true
0499                 }
0500             }
0501             else if (m_empty_input_policy == EmptyInputPolicy::IncludeEverything) {
0502                 auto databundles = facset->GetDatabundles(std::type_index(typeid(PodioT)));
0503                 for (auto* databundle : databundles) {
0504                     if (databundle->GetFactory() != nullptr) {
0505                         FactoryCreate(event, databundle->GetFactory());
0506                     }
0507                     auto typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0508                     if (typed_databundle == nullptr) {
0509                         throw JException("Not a JPodioDatabundle: type_name=%s, unique_name=%s", databundle->GetTypeName().c_str(), databundle->GetUniqueName().c_str());
0510                     }
0511                     auto typed_collection = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0512                     if (typed_collection == nullptr) {
0513                         throw JException("Podio collection is not a %s: type_name=%s, unique_name=%s", JTypeInfo::demangle<PodioT>().c_str(), databundle->GetTypeName().c_str(), databundle->GetUniqueName().c_str());
0514                     }
0515                     m_datas.push_back(typed_collection);
0516 
0517                     if (databundle->HasShortName()) {
0518                         m_realized_databundle_names.push_back(databundle->GetShortName());
0519                     }
0520                     else {
0521                         m_realized_databundle_names.push_back(databundle->GetUniqueName());
0522                     }
0523                 }
0524             }
0525         }
0526     };
0527 #endif
0528 
0529     void WireInputs(JEventLevel component_level,
0530                     const std::vector<JEventLevel>& single_input_levels,
0531                     const std::vector<std::string>& single_input_databundle_names,
0532                     const std::vector<JEventLevel>& variadic_input_levels,
0533                     const std::vector<std::vector<std::string>>& variadic_input_databundle_names) {
0534 
0535         if (m_variadic_inputs.size() == 1 && variadic_input_databundle_names.size() == 0) {
0536             WireInputsCompatibility(component_level, single_input_levels, single_input_databundle_names);
0537             return;
0538         }
0539 
0540         if (!single_input_databundle_names.empty()) {
0541 
0542             // Validate that we have the correct number of input databundle names
0543             if (single_input_databundle_names.size() != m_inputs.size()) {
0544                 throw JException("Wrong number of (nonvariadic) input databundle names! Expected %d, found %d", m_inputs.size(), single_input_databundle_names.size());
0545             }
0546 
0547             size_t i = 0;
0548             for (auto* input : m_inputs) {
0549                 input->SetDatabundleName(single_input_databundle_names.at(i));
0550                 if (single_input_levels.empty()) {
0551                     input->SetLevel(component_level);
0552                 }
0553                 else {
0554                     input->SetLevel(single_input_levels.at(i));
0555                 }
0556                 i += 1;
0557             }
0558         }
0559 
0560         if (!variadic_input_databundle_names.empty()) {
0561 
0562             // Validate that we have the correct number of variadic input databundle names
0563             if (variadic_input_databundle_names.size() != m_variadic_inputs.size()) {
0564                 throw JException("Wrong number of lists of variadic input databundle names! Expected %d, found %d", m_variadic_inputs.size(), variadic_input_databundle_names.size());
0565             }
0566 
0567             size_t i = 0;
0568             for (auto* variadic_input : m_variadic_inputs) {
0569                 variadic_input->SetRequestedDatabundleNames(variadic_input_databundle_names.at(i));
0570                 if (variadic_input_levels.empty()) {
0571                     variadic_input->SetLevel(component_level);
0572                 }
0573                 else {
0574                     variadic_input->SetLevel(variadic_input_levels.at(i));
0575                 }
0576                 i += 1;
0577             }
0578         }
0579     }
0580 
0581     void WireInputsCompatibility(JEventLevel component_level,
0582                     const std::vector<JEventLevel>& single_input_levels,
0583                     const std::vector<std::string>& single_input_databundle_names) {
0584 
0585         // Figure out how many collection names belong to the variadic input
0586         int variadic_databundle_count = single_input_databundle_names.size() - m_inputs.size();
0587         int databundle_name_index = 0;
0588         int databundle_level_index = 0;
0589 
0590         for (auto& pair : m_ordered_inputs) {
0591             auto* single_input = pair.first;
0592             auto* variadic_input = pair.second;
0593             if (single_input != nullptr) {
0594                 single_input->SetDatabundleName(single_input_databundle_names.at(databundle_name_index));
0595                 if (single_input_levels.empty()) {
0596                     single_input->SetLevel(component_level);
0597                 }
0598                 else {
0599                     single_input->SetLevel(single_input_levels.at(databundle_level_index));
0600                 }
0601                 databundle_name_index += 1;
0602                 databundle_level_index += 1;
0603             }
0604             else {
0605                 std::vector<std::string> variadic_databundle_names;
0606                 for (int i=0; i<variadic_databundle_count; ++i) {
0607                     variadic_databundle_names.push_back(single_input_databundle_names.at(databundle_name_index+i));
0608                 }
0609                 variadic_input->SetRequestedDatabundleNames(variadic_databundle_names);
0610                 if (single_input_levels.empty()) {
0611                     variadic_input->SetLevel(component_level);
0612                 }
0613                 else {
0614                     variadic_input->SetLevel(single_input_levels.at(databundle_level_index)); // Last one wins!
0615                 }
0616                 databundle_name_index += variadic_databundle_count;
0617                 databundle_level_index += 1;
0618             }
0619         }
0620     }
0621 
0622     void SummarizeInputs(JComponentSummary::Component& summary) const {
0623         for (const auto* input : m_inputs) {
0624             summary.AddInput(new JComponentSummary::Collection("", input->GetDatabundleName(), input->GetTypeName(), input->GetLevel()));
0625         }
0626         for (const auto* input : m_variadic_inputs) {
0627             for (auto& databundle_name : input->GetRequestedDatabundleNames()) {
0628                 summary.AddInput(new JComponentSummary::Collection("", databundle_name, input->GetTypeName(), input->GetLevel()));
0629             }
0630         }
0631     }
0632 };
0633 
0634 } // namespace jana::components
0635