diff --git a/src/libraries/JANA/Components/JWiredFactoryGeneratorT.h b/src/libraries/JANA/Components/JWiredFactoryGeneratorT.h new file mode 100644 index 000000000..c12c41d9d --- /dev/null +++ b/src/libraries/JANA/Components/JWiredFactoryGeneratorT.h @@ -0,0 +1,56 @@ +// Copyright 2025, Jefferson Science Associates, LLC. +// Subject to the terms in the LICENSE file found in the top-level directory. +// Created by Nathan Brei + +#pragma once + +#include +#include +#include + + +namespace jana::components { + +template +class JWiredFactoryGeneratorT : public JFactoryGenerator { + +public: + using FactoryConfigType = typename FactoryT::ConfigType; + + explicit JWiredFactoryGeneratorT() = default; + + void GenerateFactories(JFactorySet *factory_set) override { + + auto wiring_svc = GetApplication()->template GetService(); + const auto& type_name = JTypeInfo::demangle(); + for (const auto* wiring : wiring_svc->GetWirings(GetPluginName(), type_name)) { + + FactoryT *factory = new FactoryT; + factory->SetApplication(GetApplication()); + factory->SetPluginName(this->GetPluginName()); + factory->SetTypeName(type_name); + + // Set the parameter values on the factory. This way, the values in the wiring file + // show up as "defaults" and the values set on the command line show up as "overrides". + factory->ConfigureAllParameters(wiring->configs); + + // Check that output levels in wiring file match the factory's level + for (auto output_level : wiring->output_levels) { + if (output_level != wiring->level) { + throw JException("JOmniFactories are constrained to a single output level"); + } + } + + factory->PreInit(wiring->prefix, + wiring->level, + wiring->input_names, + wiring->input_levels, + wiring->output_names); + + factory_set->Add(factory); + } + } +}; + +} // namespace jana::components +using jana::components::JWiredFactoryGeneratorT; diff --git a/src/libraries/JANA/Services/JWiringService.cc b/src/libraries/JANA/Services/JWiringService.cc index 0056e371b..5ff58ef14 100644 --- a/src/libraries/JANA/Services/JWiringService.cc +++ b/src/libraries/JANA/Services/JWiringService.cc @@ -72,7 +72,7 @@ void JWiringService::AddWirings(const toml::table& table, const std::string& sou } auto& f = *fac.as_table(); - wiring->plugin_name = f["plugin_name"].value().value(); + wiring->plugin_name = f["plugin_name"].value().value_or(""); wiring->type_name = f["type_name"].value().value(); wiring->prefix = f["prefix"].value().value(); diff --git a/src/programs/unit_tests/Services/JWiringServiceTests.cc b/src/programs/unit_tests/Services/JWiringServiceTests.cc index ed44a4c28..893ef3fe5 100644 --- a/src/programs/unit_tests/Services/JWiringServiceTests.cc +++ b/src/programs/unit_tests/Services/JWiringServiceTests.cc @@ -1,6 +1,6 @@ #include "JANA/Components/JOmniFactory.h" -#include "JANA/Components/JOmniFactoryGeneratorT.h" +#include "JANA/Components/JWiredFactoryGeneratorT.h" #include #include "JANA/JException.h" #include "JANA/Utils/JEventLevel.h" @@ -207,39 +207,60 @@ struct WiredOmniFac : jana::components::JOmniFactory { } }; -TEST_CASE("WiringTests_RealFacGen") { +static constexpr std::string_view realfacgen_wiring = R"( + [[factory]] + type_name = "WiredOmniFac" + prefix = "myfac" + input_names = ["usual_input"] + output_names = ["usual_output"] - JApplication app; + [factory.configs] + x = "22" + y = "verbose" - auto wiring_svc = app.GetService(); - toml::table table = toml::parse(fake_wiring_file); - wiring_svc->AddWirings(table, "testcase"); + [[factory]] + type_name = "WiredOmniFac" + prefix = "myfac_modified" + input_names = ["different_input"] + output_names = ["different_output"] - auto gen = new jana::components::JOmniFactoryGeneratorT; + [factory.configs] + x = "100" + y = "silent" - // One gets overlaid with an existing wiring - gen->AddWiring("variantfac", {"protoclusters"}, {"clusters"}, {{"x","42"}}); +)"; - // The other is brand new - gen->AddWiring("exuberantfac", {"protoclusters"}, {"wackyclusters"}, {{"x","27"}}); +TEST_CASE("WiringTests_RealFacGen") { - // We should end up with three in total + JApplication app; + + auto wiring_svc = app.GetService(); + toml::table table = toml::parse(realfacgen_wiring); + wiring_svc->AddWirings(table, "testcase"); + auto gen = new jana::components::JWiredFactoryGeneratorT; app.Add(gen); app.Initialize(); auto& summary = app.GetComponentSummary(); - LOG << summary; - auto vf = summary.FindComponents("variantfac"); + jout << summary; + auto vf = summary.FindComponents("myfac"); REQUIRE(vf.size() == 1); - REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "clusters"); + REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "usual_output"); - auto ef = summary.FindComponents("exuberantfac"); + auto ef = summary.FindComponents("myfac_modified"); REQUIRE(ef.size() == 1); - REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "wackyclusters"); + REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "different_output"); + + // Check that parameter values propagated from wiring file to parameter manager + REQUIRE(app.GetParameterValue("myfac:x") == 22); + REQUIRE(app.GetParameterValue("myfac:y") == "verbose"); + REQUIRE(app.GetParameterValue("myfac_modified:x") == 100); + REQUIRE(app.GetParameterValue("myfac_modified:y") == "silent"); - auto event = std::make_shared(&app); - auto facs = event->GetFactorySet()->GetAllMultifactories(); + //app.GetJParameterManager()->PrintParameters(2, 0); + //auto event = std::make_shared(&app); + //auto facs = event->GetFactorySet()->GetAllMultifactories(); }