The Gaudi Framework  v33r0 (d5ea422b)
PropertyHolder.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef GAUDIKERNEL_PROPERTYHOLDER_H
12 #define GAUDIKERNEL_PROPERTYHOLDER_H
13 // ============================================================================
14 // Include files
15 // ============================================================================
16 // STD & STL
17 // ============================================================================
18 #include <algorithm>
19 #include <functional>
20 #include <iostream>
21 #include <stdexcept>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 // ============================================================================
26 // GaudiKernel
27 // ============================================================================
28 #include "GaudiKernel/Bootstrap.h"
31 #include "GaudiKernel/IProperty.h"
33 #include "GaudiKernel/MsgStream.h"
34 #include "GaudiKernel/Property.h"
35 #include "GaudiKernel/detected.h"
36 
37 // ============================================================================
38 namespace Gaudi {
39  namespace Details {
40 
41  template <typename T>
43 
44  template <typename TYPE, typename VERIFIER, typename HANDLERS>
45  struct is_gaudi_property<Gaudi::Property<TYPE, VERIFIER, HANDLERS>> : std::true_type {};
46 
47  template <typename T>
49  template <typename T>
50  using PropertyType = Gaudi::cpp17::detected_or_t<Gaudi::Property<T>, PropertyType_t, T>;
51  } // namespace Details
52  namespace Utils {
54  inline bool iequal( const std::string& v1, const std::string& v2 ) {
55  return v1.size() == v2.size() && std::equal( std::begin( v1 ), std::end( v1 ), std::begin( v2 ),
56  []( char c1, char c2 ) { return toupper( c1 ) == toupper( c2 ); } );
57  }
58  } // namespace Utils
59 } // namespace Gaudi
80 template <class BASE>
81 class GAUDI_API PropertyHolder : public BASE {
82  static_assert( std::is_base_of_v<IProperty, BASE> && std::is_base_of_v<INamedInterface, BASE>,
83  "PropertyHolder template argument must inherit from IProperty and INamedInterface" );
84 
85 public:
93 
94  PropertyHolder() = default;
95 
98  PropertyHolder( const PropertyHolder& ) = delete;
99  PropertyHolder& operator=( const PropertyHolder& ) = delete;
101 
102 public:
106  assertUniqueName( prop.name() );
107  m_properties.push_back( &prop );
108  return prop;
109  }
110 
113  template <typename TYPE, typename = std::enable_if_t<!Gaudi::Details::is_gaudi_property<TYPE>::value>>
115  const std::string& doc = "none" ) {
116  m_todelete.push_back( std::make_unique<Gaudi::Details::PropertyType<TYPE&>>( name, value ) );
117  Gaudi::Details::PropertyBase* p = m_todelete.back().get();
118 
119  p->setDocumentation( doc );
120  return &declareProperty( *p );
121  }
122 
125  template <class TYPE, class VERIFIER, class HANDLERS>
128  const std::string& doc = "none" ) {
129  Gaudi::Details::PropertyBase* p = &prop;
130  p->setName( name );
131 
132  p->setDocumentation( doc );
133  return &declareProperty( *p );
134  }
135 
139  const std::string& rname = "" ) {
140  if ( !rsvc ) return nullptr;
141  const std::string& nam = rname.empty() ? name : rname;
142  Gaudi::Details::PropertyBase* p = property( nam, rsvc->getProperties() );
143  m_remoteProperties.emplace_back( name, std::make_pair( rsvc, nam ) );
144  return p;
145  }
146 
148 
149  // ==========================================================================
150  // IProperty implementation
151  // ==========================================================================
156  Gaudi::Details::PropertyBase* pp = property( p.name() );
157  try {
158  if ( pp && pp->assign( p ) ) return StatusCode::SUCCESS;
159  } catch ( ... ) {}
160  return StatusCode::FAILURE;
161  }
162  // ==========================================================================
166  StatusCode setProperty( const std::string& s ) override {
168  std::string value;
169  StatusCode sc = Gaudi::Parsers::parse( name, value, s );
170  if ( sc.isFailure() ) return sc;
171  return setProperty( name, value );
172  }
173  // ==========================================================================
177  StatusCode setProperty( const std::string& n, const std::string& v ) override {
178  Gaudi::Details::PropertyBase* p = property( n );
179  return ( p && p->fromString( v ) ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
180  }
221  template <class TYPE>
222  StatusCode setProperty( const std::string& name, const TYPE& value ) {
223  return Gaudi::Utils::setProperty( this, name, value );
224  }
225  // ==========================================================================
230  try {
231  const Gaudi::Details::PropertyBase* pp = property( p->name() );
232  if ( pp && pp->load( *p ) ) return StatusCode::SUCCESS;
233  } catch ( ... ) {}
234  return StatusCode::FAILURE;
235  }
236  // ==========================================================================
240  const Gaudi::Details::PropertyBase& getProperty( const std::string& name ) const override {
241  const Gaudi::Details::PropertyBase* p = property( name );
242  if ( !p ) throw std::out_of_range( "Property " + name + " not found." );
243  return *p;
244  }
245  // ==========================================================================
249  StatusCode getProperty( const std::string& n, std::string& v ) const override {
250  // get the property
251  const Gaudi::Details::PropertyBase* p = property( n );
252  if ( !p ) return StatusCode::FAILURE;
253  // convert the value into the string
254  v = p->toString();
255  return StatusCode::SUCCESS;
256  }
257  // ==========================================================================
261  const std::vector<Gaudi::Details::PropertyBase*>& getProperties() const override { return m_properties; }
262  // ==========================================================================
266  bool hasProperty( const std::string& name ) const override {
267  return any_of( begin( m_properties ), end( m_properties ), [&name]( const Gaudi::Details::PropertyBase* prop ) {
268  return Gaudi::Utils::iequal( prop->name(), name );
269  } );
270  }
271  // ==========================================================================
272 protected:
273  // get local or remote property by name
275  // local property ?
276  Gaudi::Details::PropertyBase* lp = property( name, m_properties );
277  if ( lp ) return lp;
278  // look for remote property
279  for ( const auto& it : m_remoteProperties ) {
280  if ( !Gaudi::Utils::iequal( it.first, name ) ) continue;
281  const IProperty* p = it.second.first;
282  if ( !p ) continue;
283  return property( it.second.second, p->getProperties() );
284  }
285  return nullptr; // RETURN
286  }
287 
288 private:
291  const std::vector<Gaudi::Details::PropertyBase*>& props ) const {
292  auto it = std::find_if( props.begin(), props.end(), [&name]( Gaudi::Details::PropertyBase* p ) {
293  return p && Gaudi::Utils::iequal( p->name(), name );
294  } );
295  return ( it != props.end() ) ? *it : nullptr; // RETURN
296  }
297 
300  void assertUniqueName( const std::string& name ) const {
301  if ( UNLIKELY( hasProperty( name ) ) ) {
302  auto msgSvc = Gaudi::svcLocator()->service<IMessageSvc>( "MessageSvc" );
303  if ( !msgSvc ) std::cerr << "error: cannot get MessageSvc!" << std::endl;
304  MsgStream log( msgSvc, this->name() );
305  log << MSG::WARNING << "duplicated property name '" << name << "', see https://its.cern.ch/jira/browse/GAUDI-1023"
306  << endmsg;
307  }
308  }
309 
313 
320 };
321 #endif
StatusCode setProperty(IProperty *component, const std::string &name, const TYPE &value, const std::string &doc)
simple function to set the property of the given object from the value
Definition: Property.h:1207
#define UNLIKELY(x)
Definition: Kernel.h:106
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:34
T empty(T... args)
Gaudi::Details::PropertyBase * property(const std::string &name, const std::vector< Gaudi::Details::PropertyBase * > &props) const
get the property by name form the proposed list
Gaudi::Details::PropertyBase * property(const std::string &name) const
void setDocumentation(std::string value)
set the documentation string
Definition: Property.h:98
StatusCode setProperty(const std::string &name, const TYPE &value)
set the property form the value
Implementation of property with value of concrete type.
Definition: Property.h:370
StatusCode setProperty(const Gaudi::Details::PropertyBase &p) override
set the property form another property
Properties m_properties
Collection of all declared properties.
GAUDI_API bool hasProperty(const IProperty *p, const std::string &name)
simple function which check the existence of the property with the given name.
Definition: Property.cpp:105
Gaudi::cpp17::detected_or_t< Gaudi::Property< T >, PropertyType_t, T > PropertyType
T endl(T... args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:96
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Details::PropertyBase &prop)
Declare a property.
StatusCode parse(GaudiUtils::HashMap< K, V > &result, const std::string &input)
Basic parser for the types of HashMap used in DODBasicMapper.
T end(T... args)
const std::string name() const
property name
Definition: Property.h:46
bool hasProperty(const std::string &name) const override
Return true if we have a property with the given name.
std::vector< Gaudi::Details::PropertyBase * > Properties
virtual StatusCode fromString(const std::string &value)=0
string -> value
std::vector< RemProperty > RemoteProperties
STL class.
typename std::remove_reference_t< T >::PropertyType PropertyType_t
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:86
RemoteProperties m_remoteProperties
Collection of all declared remote properties.
GAUDI_API ISvcLocator * svcLocator()
StatusCode getProperty(const std::string &n, std::string &v) const override
convert the property to the string
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
bool iequal(const std::string &v1, const std::string &v2)
Helper for case insensitive string comparison.
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, Gaudi::Property< TYPE, VERIFIER, HANDLERS > &prop, const std::string &doc="none")
Declare a PropertyBase instance setting name and documentation.
The IMessage is the interface implemented by the message service.
Definition: IMessageSvc.h:47
bool PyHelper() setProperty(IInterface *p, char *name, char *value)
Definition: Bootstrap.cpp:243
T make_pair(T... args)
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:42
std::pair< std::string, std::pair< IProperty *, std::string > > RemProperty
def end
Definition: IOTest.py:123
void setName(std::string value)
set the new value for the property name
Definition: Property.h:96
T find_if(T... args)
T size(T... args)
T begin(T... args)
StatusCode setProperty(const std::string &n, const std::string &v) override
set the property from name and the value
void assertUniqueName(const std::string &name) const
Issue a runtime warning if the name is already present in the list of properties (see GAUDI-1023).
Helper class to implement the IProperty interface.
virtual const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const =0
Get list of properties.
string s
Definition: gaudirun.py:328
constexpr static const auto FAILURE
Definition: StatusCode.h:97
StatusCode getProperty(Gaudi::Details::PropertyBase *p) const override
get the property
const Gaudi::Details::PropertyBase & getProperty(const std::string &name) const override
get the property by name
const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const override
get all properties
bool isFailure() const
Definition: StatusCode.h:141
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Gaudi::Details::PropertyBase * declareRemoteProperty(const std::string &name, IProperty *rsvc, const std::string &rname="")
Declare a remote property.
The IProperty is the basic interface for all components which have properties that can be set or get.
Definition: IProperty.h:30
std::vector< std::unique_ptr< Gaudi::Details::PropertyBase > > m_todelete
Properties owned by PropertyHolder, to be deleted.
#define GAUDI_API
Definition: Kernel.h:81
StatusCode setProperty(const std::string &s) override
set the property from the formatted string
T equal(T... args)
virtual std::string toString() const =0
value -> string
void toupper(std::string &s)
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:202
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, TYPE &value, const std::string &doc="none")
Helper to wrap a regular data member and use it as a regular property.