File indexing completed on 2025-01-18 09:57:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef GAUDIKERNEL_PROPERTYHOLDER_H
0012 #define GAUDIKERNEL_PROPERTYHOLDER_H
0013
0014
0015
0016
0017
0018 #include <algorithm>
0019 #include <functional>
0020 #include <iostream>
0021 #include <stdexcept>
0022 #include <string>
0023 #include <utility>
0024 #include <vector>
0025
0026
0027
0028 #include "GaudiKernel/Bootstrap.h"
0029 #include "GaudiKernel/DataHandleProperty.h"
0030 #include "GaudiKernel/INamedInterface.h"
0031 #include "GaudiKernel/IProperty.h"
0032 #include "GaudiKernel/ISvcLocator.h"
0033 #include "GaudiKernel/MsgStream.h"
0034 #include "GaudiKernel/detected.h"
0035 #include <Gaudi/Property.h>
0036
0037 #include "Gaudi/Interfaces/IOptionsSvc.h"
0038
0039 namespace Gaudi {
0040 namespace Details {
0041
0042 template <typename T>
0043 struct is_gaudi_property : std::false_type {};
0044
0045 template <typename TYPE, typename VERIFIER, typename HANDLERS>
0046 struct is_gaudi_property<Gaudi::Property<TYPE, VERIFIER, HANDLERS>> : std::true_type {};
0047
0048 template <typename T>
0049 using PropertyType_t = typename std::remove_reference_t<T>::PropertyType;
0050 template <typename T>
0051 using PropertyType = Gaudi::cpp17::detected_or_t<Gaudi::Property<T>, PropertyType_t, T>;
0052 }
0053 namespace Utils {
0054
0055 inline bool iequal( std::string_view v1, std::string_view v2 ) {
0056 return std::equal( begin( v1 ), end( v1 ), begin( v2 ), end( v2 ),
0057 []( char c1, char c2 ) { return toupper( c1 ) == toupper( c2 ); } );
0058 }
0059 }
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 template <class BASE>
0082 class GAUDI_API PropertyHolder : public BASE {
0083 static_assert( std::is_base_of_v<IProperty, BASE> && std::is_base_of_v<INamedInterface, BASE>,
0084 "PropertyHolder template argument must inherit from IProperty and INamedInterface" );
0085
0086 public:
0087
0088
0089
0090
0091
0092
0093 using PropertyHolderImpl = PropertyHolder<BASE>;
0094
0095 PropertyHolder() = default;
0096
0097
0098
0099 PropertyHolder( const PropertyHolder& ) = delete;
0100 PropertyHolder& operator=( const PropertyHolder& ) = delete;
0101
0102
0103 public:
0104
0105
0106 inline Gaudi::Details::PropertyBase& declareProperty( Gaudi::Details::PropertyBase& prop ) {
0107 assertUniqueName( prop.name() );
0108 m_properties.push_back( &prop );
0109 return prop;
0110 }
0111
0112
0113
0114 template <typename TYPE, typename = std::enable_if_t<!Gaudi::Details::is_gaudi_property<TYPE>::value>>
0115 Gaudi::Details::PropertyBase* declareProperty( const std::string& name, TYPE& value,
0116 const std::string& doc = "none" ) {
0117 m_todelete.push_back( std::make_unique<Gaudi::Details::PropertyType<TYPE&>>( name, value ) );
0118 Gaudi::Details::PropertyBase* p = m_todelete.back().get();
0119
0120 p->setDocumentation( doc );
0121 return &declareProperty( *p );
0122 }
0123
0124
0125
0126 template <class TYPE, class VERIFIER, class HANDLERS>
0127 Gaudi::Details::PropertyBase* declareProperty( const std::string& name,
0128 Gaudi::Property<TYPE, VERIFIER, HANDLERS>& prop,
0129 const std::string& doc = "none" ) {
0130 Gaudi::Details::PropertyBase* p = ∝
0131 p->setName( name );
0132
0133 p->setDocumentation( doc );
0134 return &declareProperty( *p );
0135 }
0136
0137
0138
0139 Gaudi::Details::PropertyBase* declareRemoteProperty( const std::string& name, IProperty* rsvc,
0140 const std::string& rname = "" ) {
0141 if ( !rsvc ) return nullptr;
0142 const std::string& nam = rname.empty() ? name : rname;
0143 Gaudi::Details::PropertyBase* p = property( nam, rsvc->getProperties() );
0144 m_remoteProperties.emplace_back( RemProperty{ name, rsvc, nam } );
0145 return p;
0146 }
0147
0148
0149
0150
0151
0152
0153 using IProperty::setProperty;
0154
0155
0156
0157 StatusCode setProperty( const std::string& name, const Gaudi::Details::PropertyBase& p ) override {
0158 Gaudi::Details::PropertyBase* pp = property( name );
0159 if ( pp && pp->assign( p ) ) return StatusCode::SUCCESS;
0160 return StatusCode::FAILURE;
0161 }
0162
0163
0164
0165
0166 StatusCode setProperty( const std::string& s ) override {
0167 std::string name;
0168 std::string value;
0169 StatusCode sc = Gaudi::Parsers::parse( name, value, s );
0170 if ( sc.isFailure() ) return sc;
0171 return setPropertyRepr( name, value );
0172 }
0173
0174
0175
0176
0177 StatusCode setPropertyRepr( const std::string& n, const std::string& r ) override {
0178 try {
0179 Gaudi::Details::PropertyBase* p = property( n );
0180
0181 return ( p && p->fromString( r ) ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
0182 } catch ( const std::invalid_argument& err ) {
0183 throw GaudiException{ "error setting property " + n, this->name(), StatusCode::FAILURE, err };
0184 }
0185 }
0186
0187
0188
0189
0190 StatusCode getProperty( Gaudi::Details::PropertyBase* p ) const override {
0191 try {
0192 const Gaudi::Details::PropertyBase* pp = property( p->name() );
0193 if ( pp && pp->load( *p ) ) return StatusCode::SUCCESS;
0194 } catch ( ... ) {}
0195 return StatusCode::FAILURE;
0196 }
0197
0198
0199
0200
0201 const Gaudi::Details::PropertyBase& getProperty( std::string_view name ) const override {
0202 const Gaudi::Details::PropertyBase* p = property( name );
0203 if ( !p ) throw std::out_of_range( "Property " + std::string{ name } + " not found." );
0204 return *p;
0205 }
0206
0207
0208
0209
0210 StatusCode getProperty( std::string_view n, std::string& v ) const override {
0211
0212 const Gaudi::Details::PropertyBase* p = property( n );
0213 if ( !p ) return StatusCode::FAILURE;
0214
0215 v = p->toString();
0216 return StatusCode::SUCCESS;
0217 }
0218
0219
0220
0221
0222 const std::vector<Gaudi::Details::PropertyBase*>& getProperties() const override { return m_properties; }
0223
0224
0225
0226
0227 bool hasProperty( std::string_view name ) const override {
0228 return any_of( begin( m_properties ), end( m_properties ),
0229 [&name]( const Gaudi::Details::PropertyBase* prop ) {
0230 return Gaudi::Utils::iequal( prop->name(), name );
0231 } ) ||
0232 any_of( begin( m_remoteProperties ), end( m_remoteProperties ),
0233 [&name]( const auto& prop ) { return Gaudi::Utils::iequal( prop.name, name ); } );
0234 }
0235
0236
0237
0238 Gaudi::Details::PropertyBase* property( std::string_view name ) const {
0239
0240 Gaudi::Details::PropertyBase* lp = property( name, m_properties );
0241 if ( lp ) return lp;
0242
0243 for ( const auto& it : m_remoteProperties ) {
0244 if ( !Gaudi::Utils::iequal( it.name, name ) ) continue;
0245 const IProperty* p = it.owner;
0246 if ( !p ) continue;
0247 return property( it.remName, p->getProperties() );
0248 }
0249 return nullptr;
0250 }
0251
0252 void bindPropertiesTo( Gaudi::Interfaces::IOptionsSvc& optsSvc ) {
0253 auto set_prop = [&optsSvc, this]( auto prop ) { optsSvc.bind( this->name(), prop ); };
0254 std::for_each( begin( m_properties ), end( m_properties ), set_prop );
0255 std::for_each( begin( m_remoteProperties ), end( m_remoteProperties ), [&set_prop, this]( auto& rem ) {
0256 if ( rem.owner ) set_prop( this->property( rem.remName, rem.owner->getProperties() ) );
0257 } );
0258 }
0259
0260 private:
0261
0262 Gaudi::Details::PropertyBase* property( std::string_view name,
0263 const std::vector<Gaudi::Details::PropertyBase*>& props ) const {
0264 auto it = std::find_if( props.begin(), props.end(), [name]( Gaudi::Details::PropertyBase* p ) {
0265 return p && Gaudi::Utils::iequal( p->name(), name );
0266 } );
0267 return ( it != props.end() ) ? *it : nullptr;
0268 }
0269
0270
0271
0272 void assertUniqueName( std::string_view name ) const {
0273 if ( hasProperty( name ) ) {
0274 auto msgSvc = Gaudi::svcLocator()->service<IMessageSvc>( "MessageSvc" );
0275 if ( !msgSvc ) std::cerr << "error: cannot get MessageSvc!" << std::endl;
0276 MsgStream log( msgSvc, this->name() );
0277 log << MSG::WARNING << "duplicated property name '" << name << "', see https://its.cern.ch/jira/browse/GAUDI-1023"
0278 << endmsg;
0279 }
0280 }
0281
0282 typedef std::vector<Gaudi::Details::PropertyBase*> Properties;
0283 struct RemProperty {
0284 std::string name;
0285 IProperty* owner = nullptr;
0286 std::string remName;
0287 };
0288 typedef std::vector<RemProperty> RemoteProperties;
0289
0290
0291 Properties m_properties;
0292
0293 RemoteProperties m_remoteProperties;
0294
0295 std::vector<std::unique_ptr<Gaudi::Details::PropertyBase>> m_todelete;
0296 };
0297 #endif