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