File indexing completed on 2026-04-13 08:28:03
0001
0002
0003
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
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
0143
0144
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
0171
0172
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
0218
0219
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
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
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({});
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
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({});
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);
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
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
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
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));
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 }
0635