File indexing completed on 2025-11-29 10:25:01
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 auto* typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0238 if (typed_databundle == nullptr) {
0239 if (!m_is_optional) {
0240 facset->Print();
0241 throw JException("Databundle with shortname '%s' does not inherit from JLightweightDatabundleT<%s>", m_databundle_name.c_str(), JTypeInfo::demangle<T>().c_str());
0242 }
0243 }
0244 m_data.clear();
0245 m_data.insert(m_data.end(), typed_databundle->GetData().begin(), typed_databundle->GetData().end());
0246 }
0247 };
0248
0249 #if JANA2_HAVE_PODIO
0250 template <typename PodioT>
0251 class PodioInput : public InputBase {
0252
0253 const typename PodioT::collection_type* m_data;
0254
0255 public:
0256
0257 PodioInput(JHasInputs* owner) {
0258 owner->RegisterInput(this);
0259 m_type_index = std::type_index(typeid(PodioT));
0260 m_type_name = JTypeInfo::demangle<PodioT>();
0261 m_databundle_name = m_type_name;
0262 m_level = JEventLevel::None;
0263 }
0264
0265 PodioInput(JHasInputs* owner, const InputOptions& options) {
0266 owner->RegisterInput(this);
0267 m_type_index = std::type_index(typeid(PodioT));
0268 m_type_name = JTypeInfo::demangle<PodioT>();
0269 m_databundle_name = m_type_name;
0270 Configure(options);
0271 }
0272
0273 const typename PodioT::collection_type* operator()() {
0274 return m_data;
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
0283 void SetCollectionName(std::string name) {
0284 m_databundle_name = name;
0285 }
0286
0287 void SetTag(std::string tag) {
0288 m_databundle_name = m_type_name + ":" + tag;
0289 }
0290
0291 void Populate(const JEvent& event) {
0292 auto facset = GetFactorySetAtLevel(event, m_level);
0293 if (facset == nullptr) {
0294 if (m_is_optional) {
0295 return;
0296 }
0297 throw JException("Could not find parent at level=" + toString(m_level));
0298 }
0299 auto databundle = facset->GetDatabundle(std::type_index(typeid(PodioT)), m_databundle_name);
0300 if (databundle == nullptr) {
0301 if (!m_is_optional) {
0302 facset->Print();
0303 throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<PodioT>() + " and tag=" + m_databundle_name);
0304 }
0305
0306 m_data = nullptr;
0307 return;
0308 };
0309 if (databundle->GetFactory() != nullptr) {
0310 FactoryCreate(event, databundle->GetFactory());
0311 }
0312 auto* typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0313 if (typed_databundle == nullptr) {
0314 facset->Print();
0315 throw JException("Databundle with unique name '%s' does not inherit from JPodioDatabundle", databundle->GetUniqueName().c_str());
0316 }
0317 m_data = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0318 if (m_data == nullptr) {
0319 throw JException("Databundle with unique name '%s' does not contain %s", databundle->GetUniqueName().c_str(), JTypeInfo::demangle<typename PodioT::collection_type>().c_str());
0320 }
0321 }
0322 };
0323 #endif
0324
0325
0326 template <typename T>
0327 class VariadicInput : public VariadicInputBase {
0328
0329 std::vector<std::vector<const T*>> m_datas;
0330
0331 public:
0332
0333 VariadicInput(JHasInputs* owner) {
0334 owner->RegisterInput(this);
0335 m_type_index = std::type_index(typeid(T));
0336 m_type_name = JTypeInfo::demangle<T>();
0337 m_level = JEventLevel::None;
0338 }
0339
0340 VariadicInput(JHasInputs* owner, const VariadicInputOptions& options) {
0341 owner->RegisterInput(this);
0342 m_type_index = std::type_index(typeid(T));
0343 m_type_name = JTypeInfo::demangle<T>();
0344 Configure(options);
0345 }
0346
0347 void SetTags(std::vector<std::string> tags) {
0348 m_requested_databundle_names = tags;
0349 m_realized_databundle_names = tags;
0350 }
0351
0352 const std::vector<std::vector<const T*>>& operator()() { return m_datas; }
0353 const std::vector<std::vector<const T*>>& operator*() { return m_datas; }
0354 const std::vector<std::vector<const T*>>* operator->() { return &m_datas; }
0355
0356 const std::vector<const T*>& operator()(size_t index) { return m_datas.at(index); }
0357
0358
0359 private:
0360 friend class JComponentT;
0361
0362 void Populate(const JEvent& event) {
0363 m_datas.clear();
0364 auto facset = GetFactorySetAtLevel(event, m_level);
0365 if (facset == nullptr) {
0366 if (m_is_optional) {
0367 return;
0368 }
0369 throw JException("Could not find parent at level=" + toString(m_level));
0370 }
0371 if (!m_requested_databundle_names.empty()) {
0372
0373 for (auto& short_or_unique_name : m_requested_databundle_names) {
0374 auto databundle = facset->GetDatabundle(std::type_index(typeid(T)), short_or_unique_name);
0375 if (databundle == nullptr) {
0376 if (!m_is_optional) {
0377 facset->Print();
0378 throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<T>() + " and name=" + short_or_unique_name);
0379 }
0380 m_datas.push_back({});
0381 continue;
0382 };
0383 if (databundle->GetFactory() != nullptr) {
0384 FactoryCreate(event, databundle->GetFactory());
0385 }
0386 auto* typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0387 if (typed_databundle == nullptr) {
0388 facset->Print();
0389 throw JException("Databundle with shortname '%s' does not inherit from JLightweightDatabundleT<%s>", short_or_unique_name.c_str(), JTypeInfo::demangle<T>().c_str());
0390 }
0391 m_datas.push_back({});
0392 auto& dest = m_datas.back();
0393 dest.insert(dest.end(), typed_databundle->GetData().begin(), typed_databundle->GetData().end());
0394 }
0395 }
0396 else if (m_empty_input_policy == EmptyInputPolicy::IncludeEverything) {
0397
0398 m_realized_databundle_names.clear();
0399
0400 auto databundles = facset->GetDatabundles(std::type_index(typeid(T)));
0401 for (auto* databundle : databundles) {
0402
0403 auto typed_databundle = dynamic_cast<JLightweightDatabundleT<T>*>(databundle);
0404 if (typed_databundle == nullptr) {
0405 throw JException("Databundle with name=" + typed_databundle->GetUniqueName() + " does not inherit from JLightweightDatabundleT<" + JTypeInfo::demangle<T>() + ">");
0406 }
0407 auto& contents = typed_databundle->GetData();
0408 m_datas.push_back({});
0409 auto& dest = m_datas.back();
0410 dest.insert(dest.end(), contents.begin(), contents.end());
0411 if (databundle->HasShortName()) {
0412 m_realized_databundle_names.push_back(databundle->GetShortName());
0413 }
0414 else {
0415 m_realized_databundle_names.push_back(databundle->GetUniqueName());
0416 }
0417 }
0418 }
0419 }
0420 };
0421
0422
0423
0424 #if JANA2_HAVE_PODIO
0425 template <typename PodioT>
0426 class VariadicPodioInput : public VariadicInputBase {
0427
0428 std::vector<const typename PodioT::collection_type*> m_datas;
0429
0430 public:
0431
0432 VariadicPodioInput(JHasInputs* owner) {
0433 owner->RegisterInput(this);
0434 m_type_index = std::type_index(typeid(PodioT));
0435 m_type_name = JTypeInfo::demangle<PodioT>();
0436 }
0437
0438 VariadicPodioInput(JHasInputs* owner, const VariadicInputOptions& options) {
0439 owner->RegisterInput(this);
0440 m_type_index = std::type_index(typeid(PodioT));
0441 m_type_name = JTypeInfo::demangle<PodioT>();
0442 Configure(options);
0443 }
0444
0445 const std::vector<const typename PodioT::collection_type*> operator()() {
0446 return m_datas;
0447 }
0448
0449 void SetRequestedCollectionNames(std::vector<std::string> names) {
0450 m_requested_databundle_names = names;
0451 m_realized_databundle_names = std::move(names);
0452 }
0453
0454 const std::vector<std::string>& GetRealizedCollectionNames() {
0455 return GetRealizedDatabundleNames();
0456 }
0457
0458 void Populate(const JEvent& event) {
0459 auto facset = GetFactorySetAtLevel(event, m_level);
0460 if (facset == nullptr) {
0461 if (m_is_optional) {
0462 return;
0463 }
0464 throw JException("Could not find parent at level=" + toString(m_level));
0465 }
0466 bool need_dynamic_realized_databundle_names = (m_requested_databundle_names.empty()) && (m_empty_input_policy != EmptyInputPolicy::IncludeNothing);
0467 if (need_dynamic_realized_databundle_names) {
0468 m_realized_databundle_names.clear();
0469 }
0470 m_datas.clear();
0471 if (!m_requested_databundle_names.empty()) {
0472 for (auto& short_or_unique_name : m_requested_databundle_names) {
0473 auto databundle = facset->GetDatabundle(std::type_index(typeid(PodioT)), short_or_unique_name);
0474 if (databundle == nullptr) {
0475 if (!m_is_optional) {
0476 facset->Print();
0477 throw JException("Could not find databundle with type_index=" + JTypeInfo::demangle<PodioT>() + " and name=" + short_or_unique_name);
0478 }
0479 m_datas.push_back(nullptr);
0480 continue;
0481 }
0482 if (databundle->GetFactory() != nullptr) {
0483 FactoryCreate(event, databundle->GetFactory());
0484 }
0485 auto* typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0486 if (typed_databundle == nullptr) {
0487 facset->Print();
0488 throw JException("Databundle with name '%s' does not inherit from JPodioDatabundle", short_or_unique_name.c_str());
0489 }
0490 auto* typed_collection = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0491 if (typed_collection == nullptr) {
0492 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());
0493 }
0494
0495 m_datas.push_back(typed_collection);
0496 }
0497 }
0498 else if (m_empty_input_policy == EmptyInputPolicy::IncludeEverything) {
0499 auto databundles = facset->GetDatabundles(std::type_index(typeid(PodioT)));
0500 for (auto* databundle : databundles) {
0501 if (databundle->GetFactory() != nullptr) {
0502 FactoryCreate(event, databundle->GetFactory());
0503 }
0504 auto typed_databundle = dynamic_cast<JPodioDatabundle*>(databundle);
0505 if (typed_databundle == nullptr) {
0506 throw JException("Not a JPodioDatabundle: type_name=%s, unique_name=%s", databundle->GetTypeName().c_str(), databundle->GetUniqueName().c_str());
0507 }
0508 auto typed_collection = dynamic_cast<const typename PodioT::collection_type*>(typed_databundle->GetCollection());
0509 if (typed_collection == nullptr) {
0510 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());
0511 }
0512 m_datas.push_back(typed_collection);
0513
0514 if (databundle->HasShortName()) {
0515 m_realized_databundle_names.push_back(databundle->GetShortName());
0516 }
0517 else {
0518 m_realized_databundle_names.push_back(databundle->GetUniqueName());
0519 }
0520 }
0521 }
0522 }
0523 };
0524 #endif
0525
0526 void WireInputs(JEventLevel component_level,
0527 const std::vector<JEventLevel>& single_input_levels,
0528 const std::vector<std::string>& single_input_databundle_names,
0529 const std::vector<JEventLevel>& variadic_input_levels,
0530 const std::vector<std::vector<std::string>>& variadic_input_databundle_names) {
0531
0532 if (m_variadic_inputs.size() == 1 && variadic_input_databundle_names.size() == 0) {
0533 WireInputsCompatibility(component_level, single_input_levels, single_input_databundle_names);
0534 return;
0535 }
0536
0537 if (!single_input_databundle_names.empty()) {
0538
0539
0540 if (single_input_databundle_names.size() != m_inputs.size()) {
0541 throw JException("Wrong number of (nonvariadic) input databundle names! Expected %d, found %d", m_inputs.size(), single_input_databundle_names.size());
0542 }
0543
0544 size_t i = 0;
0545 for (auto* input : m_inputs) {
0546 input->SetDatabundleName(single_input_databundle_names.at(i));
0547 if (single_input_levels.empty()) {
0548 input->SetLevel(component_level);
0549 }
0550 else {
0551 input->SetLevel(single_input_levels.at(i));
0552 }
0553 i += 1;
0554 }
0555 }
0556
0557 if (!variadic_input_databundle_names.empty()) {
0558
0559
0560 if (variadic_input_databundle_names.size() != m_variadic_inputs.size()) {
0561 throw JException("Wrong number of lists of variadic input databundle names! Expected %d, found %d", m_variadic_inputs.size(), variadic_input_databundle_names.size());
0562 }
0563
0564 size_t i = 0;
0565 for (auto* variadic_input : m_variadic_inputs) {
0566 variadic_input->SetRequestedDatabundleNames(variadic_input_databundle_names.at(i));
0567 if (variadic_input_levels.empty()) {
0568 variadic_input->SetLevel(component_level);
0569 }
0570 else {
0571 variadic_input->SetLevel(variadic_input_levels.at(i));
0572 }
0573 i += 1;
0574 }
0575 }
0576 }
0577
0578 void WireInputsCompatibility(JEventLevel component_level,
0579 const std::vector<JEventLevel>& single_input_levels,
0580 const std::vector<std::string>& single_input_databundle_names) {
0581
0582
0583 int variadic_databundle_count = single_input_databundle_names.size() - m_inputs.size();
0584 int databundle_name_index = 0;
0585 int databundle_level_index = 0;
0586
0587 for (auto& pair : m_ordered_inputs) {
0588 auto* single_input = pair.first;
0589 auto* variadic_input = pair.second;
0590 if (single_input != nullptr) {
0591 single_input->SetDatabundleName(single_input_databundle_names.at(databundle_name_index));
0592 if (single_input_levels.empty()) {
0593 single_input->SetLevel(component_level);
0594 }
0595 else {
0596 single_input->SetLevel(single_input_levels.at(databundle_level_index));
0597 }
0598 databundle_name_index += 1;
0599 databundle_level_index += 1;
0600 }
0601 else {
0602 std::vector<std::string> variadic_databundle_names;
0603 for (int i=0; i<variadic_databundle_count; ++i) {
0604 variadic_databundle_names.push_back(single_input_databundle_names.at(databundle_name_index+i));
0605 }
0606 variadic_input->SetRequestedDatabundleNames(variadic_databundle_names);
0607 if (single_input_levels.empty()) {
0608 variadic_input->SetLevel(component_level);
0609 }
0610 else {
0611 variadic_input->SetLevel(single_input_levels.at(databundle_level_index));
0612 }
0613 databundle_name_index += variadic_databundle_count;
0614 databundle_level_index += 1;
0615 }
0616 }
0617 }
0618
0619 void SummarizeInputs(JComponentSummary::Component& summary) const {
0620 for (const auto* input : m_inputs) {
0621 summary.AddInput(new JComponentSummary::Collection("", input->GetDatabundleName(), input->GetTypeName(), input->GetLevel()));
0622 }
0623 for (const auto* input : m_variadic_inputs) {
0624 for (auto& databundle_name : input->GetRequestedDatabundleNames()) {
0625 summary.AddInput(new JComponentSummary::Collection("", databundle_name, input->GetTypeName(), input->GetLevel()));
0626 }
0627 }
0628 }
0629 };
0630
0631 }
0632