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