The Gaudi Framework  v32r2 (46d42edc)
SplittingTransformer.h
Go to the documentation of this file.
1 #ifndef SPLITTING_TRANSFORMER_H
2 #define SPLITTING_TRANSFORMER_H
3 
4 #include <functional>
5 #include <optional>
6 #include <string>
7 #include <vector>
8 
11 
12 namespace Gaudi::Functional {
13 
14  template <typename Container>
16  template <typename Container>
18 
19  namespace details {
20 
21  template <typename Signature, typename Traits_, bool isLegacy>
23 
25  template <typename Out, typename... In, typename Traits_>
26  class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, true>
27  : public details::DataHandleMixin<void, std::tuple<In...>, Traits_> {
28  using base_class = details::DataHandleMixin<void, std::tuple<In...>, Traits_>;
29 
30  public:
31  constexpr static std::size_t N = base_class::N_in;
32  using KeyValue = typename base_class::KeyValue;
33  using KeyValues = typename base_class::KeyValues;
34 
36  const KeyValues& outputs )
37  : base_class( name, locator, inputs )
38  , m_outputLocations(
39  this, outputs.first, outputs.second,
40  [=]( Gaudi::Details::PropertyBase& ) {
41  this->m_outputs =
42  details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
43  if constexpr ( details::is_optional_v<Out> ) { // handle constructor does not (yet) allow to
44  // set optional flag... so
45  // do it explicitly here...
46  std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
47  []( auto& h ) { h.setOptional( true ); } );
48  }
49  },
51 
52  SplittingTransformer( const std::string& name, ISvcLocator* locator, const KeyValue& input,
53  const KeyValues& output )
54  : SplittingTransformer( name, locator, std::array<KeyValue, 1>{input}, output ) {
55  static_assert( N == 1, "single input argument requires single input signature" );
56  }
57 
58  // accessor to output Locations
59  const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n]; }
60  unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
61 
62  // derived classes can NOT implement execute
63  StatusCode execute() override final {
64  try {
65  // TODO:FIXME: how does operator() know the number and order of expected outputs?
66  auto out = details::filter_evtcontext_t<In...>::apply( *this, this->m_inputs );
67  if ( out.size() != m_outputs.size() ) {
68  throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
69  " containers, got " + std::to_string( out.size() ) + " instead",
70  this->name(), StatusCode::FAILURE );
71  }
72  for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
73  return StatusCode::SUCCESS;
74  } catch ( GaudiException& e ) {
75  ( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
76  return e.code();
77  }
78  }
79 
80  // TODO/FIXME: how does the callee know in which order to produce the outputs?
81  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
82  // and only those entries which contain an Out are stored)
83  virtual vector_of_<Out> operator()( const In&... ) const = 0;
84 
85  private:
86  template <typename T>
87  using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
89  Gaudi::Property<std::vector<std::string>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
90  // actual handles!
91  };
92 
93  template <typename Out, typename... In, typename Traits_>
94  class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, false>
95  : public details::DataHandleMixin<void, std::tuple<In...>, Traits_> {
96  using base_class = details::DataHandleMixin<void, std::tuple<In...>, Traits_>;
97 
98  public:
99  constexpr static std::size_t N = base_class::N_in;
100  using KeyValue = typename base_class::KeyValue;
101  using KeyValues = typename base_class::KeyValues;
102 
104  const KeyValues& outputs )
105  : base_class( name, locator, inputs )
106  , m_outputLocations(
107  this, outputs.first, outputs.second,
108  [=]( Gaudi::Details::PropertyBase& ) {
109  this->m_outputs =
110  details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
111  if constexpr ( details::is_optional_v<Out> ) { // handle constructor does not (yet) allow to
112  // set optional flag... so
113  // do it explicitly here...
114  std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
115  []( auto& h ) { h.setOptional( true ); } );
116  }
117  },
119 
120  SplittingTransformer( const std::string& name, ISvcLocator* locator, const KeyValue& input,
121  const KeyValues& output )
122  : SplittingTransformer( name, locator, std::array<KeyValue, 1>{input}, output ) {
123  static_assert( N == 1, "single input argument requires single input signature" );
124  }
125 
126  // accessor to output Locations
127  const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n]; }
128  unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
129 
130  // derived classes can NOT implement execute
131  StatusCode execute( const EventContext& ctx ) const override final {
132  try {
133  // TODO:FIXME: how does operator() know the number and order of expected outputs?
134  auto out = details::filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs );
135  if ( out.size() != m_outputs.size() ) {
136  throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
137  " containers, got " + std::to_string( out.size() ) + " instead",
138  this->name(), StatusCode::FAILURE );
139  }
140  for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
141  return StatusCode::SUCCESS;
142  } catch ( GaudiException& e ) {
143  ( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
144  return e.code();
145  }
146  }
147 
148  // TODO/FIXME: how does the callee know in which order to produce the outputs?
149  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
150  // and only those entries which contain an Out are stored)
151  virtual vector_of_<Out> operator()( const In&... ) const = 0;
152 
153  private:
154  template <typename T>
155  using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
157  Gaudi::Property<std::vector<std::string>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
158  // actual handles!
159  };
160 
161  } // namespace details
162 
163  template <typename Signature, typename Traits_ = Traits::useDefaults>
165 
166 } // namespace Gaudi::Functional
167 
168 #endif
Out1 * put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
Implementation of property with value of concrete type.
Definition: Property.h:352
SplittingTransformer(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
Gaudi::tagged_bool< class ImmediatelyInvokeHandler_tag > ImmediatelyInvokeHandler
Definition: Property.h:141
T to_string(T... args)
virtual const std::string & message() const
error message to be printed
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
STL namespace.
This class represents an entry point to all the event specific data.
Definition: EventContext.h:24
SplittingTransformer(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N > &inputs, const KeyValues &outputs)
constexpr double second
STL class.
SplittingTransformer(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N > &inputs, const KeyValues &outputs)
int N
Definition: IOTest.py:100
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
details::template vector_of_const_< Container > vector_of_
T move(T... args)
virtual const StatusCode & code() const
StatusCode for Exception.
SplittingTransformer(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
STL class.
STL class.
constexpr static const auto FAILURE
Definition: StatusCode.h:86
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init)
details::OutputHandle_t< Traits_, details::remove_optional_t< T > > OutputHandle
T for_each(T... args)
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192