File indexing completed on 2025-01-18 09:57:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #pragma once
0012
0013 #include "details.h"
0014 #include "utilities.h"
0015 #include <GaudiKernel/FunctionalFilterDecision.h>
0016 #include <functional>
0017 #include <optional>
0018 #include <string>
0019 #include <vector>
0020
0021 namespace Gaudi::Functional {
0022
0023 template <typename Container>
0024 using vector_of_ = std::vector<Container>;
0025 template <typename Container>
0026 using vector_of_optional_ = std::vector<std::optional<Container>>;
0027
0028 namespace details {
0029
0030 template <typename Signature, typename Traits_, bool isLegacy>
0031 class SplittingTransformer;
0032
0033
0034 template <typename Out, typename... In, typename Traits_>
0035 class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, true>
0036 : public details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_> {
0037 using base_class = details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_>;
0038
0039 public:
0040 constexpr static std::size_t N = base_class::N_in;
0041 using KeyValue = typename base_class::KeyValue;
0042 using KeyValues = typename base_class::KeyValues;
0043
0044 SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_<KeyValue, N>& inputs,
0045 const KeyValues& outputs )
0046 : base_class( std::move( name ), locator, inputs )
0047 , m_outputLocations(
0048 this, outputs.first, details::to_DataObjID( outputs.second ),
0049 [this]( Gaudi::Details::PropertyBase& ) {
0050 this->m_outputs =
0051 details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
0052 if constexpr ( details::is_optional_v<Out> ) {
0053
0054
0055 std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
0056 []( auto& h ) { h.setOptional( true ); } );
0057 }
0058 },
0059 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } ) {}
0060
0061 SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output )
0062 : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) {
0063 static_assert( N == 1, "single input argument requires single input signature" );
0064 }
0065
0066
0067 const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n].key(); }
0068 unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
0069
0070
0071 StatusCode execute() override final {
0072 try {
0073
0074 auto out = details::filter_evtcontext_t<In...>::apply( *this, this->m_inputs );
0075 if ( out.size() != m_outputs.size() ) {
0076 throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
0077 " containers, got " + std::to_string( out.size() ) + " instead",
0078 this->name(), StatusCode::FAILURE );
0079 }
0080 for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
0081 return FilterDecision::PASSED;
0082 } catch ( GaudiException& e ) {
0083 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0084 return e.code();
0085 }
0086 }
0087
0088
0089
0090
0091 virtual vector_of_<Out> operator()( const In&... ) const = 0;
0092
0093 private:
0094 template <typename T>
0095 using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
0096 std::vector<OutputHandle<Out>> m_outputs;
0097 Gaudi::Property<std::vector<DataObjID>> m_outputLocations;
0098
0099 };
0100
0101 template <typename Out, typename... In, typename Traits_>
0102 class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, false>
0103 : public details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_> {
0104 using base_class = details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_>;
0105
0106 public:
0107 constexpr static std::size_t N = base_class::N_in;
0108 using KeyValue = typename base_class::KeyValue;
0109 using KeyValues = typename base_class::KeyValues;
0110
0111 SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_<KeyValue, N>& inputs,
0112 const KeyValues& outputs )
0113 : base_class( std::move( name ), locator, inputs )
0114 , m_outputLocations(
0115 this, outputs.first, details::to_DataObjID( outputs.second ),
0116 [this]( Gaudi::Details::PropertyBase& ) {
0117 this->m_outputs =
0118 details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
0119 if constexpr ( details::is_optional_v<Out> ) {
0120
0121
0122 std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
0123 []( auto& h ) { h.setOptional( true ); } );
0124 }
0125 },
0126 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } ) {}
0127
0128 SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output )
0129 : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) {
0130 static_assert( N == 1, "single input argument requires single input signature" );
0131 }
0132
0133
0134 const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n].key(); }
0135 unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
0136
0137
0138 StatusCode execute( const EventContext& ctx ) const override final {
0139 try {
0140
0141 auto out = details::filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs );
0142 if ( out.size() != m_outputs.size() ) {
0143 throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
0144 " containers, got " + std::to_string( out.size() ) + " instead",
0145 this->name(), StatusCode::FAILURE );
0146 }
0147 for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
0148 return FilterDecision::PASSED;
0149 } catch ( GaudiException& e ) {
0150 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0151 return e.code();
0152 }
0153 }
0154
0155
0156
0157
0158 virtual vector_of_<Out> operator()( const In&... ) const = 0;
0159
0160 private:
0161 template <typename T>
0162 using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
0163 std::vector<OutputHandle<Out>> m_outputs;
0164 Gaudi::Property<std::vector<DataObjID>> m_outputLocations;
0165
0166 };
0167
0168 }
0169
0170 template <typename Signature, typename Traits_ = Traits::useDefaults>
0171 using SplittingTransformer = details::SplittingTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
0172
0173 }