The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
PropertyHolder.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 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#pragma once
12
14#include <Gaudi/Property.h>
21#include <algorithm>
22#include <functional>
23#include <iostream>
24#include <stdexcept>
25#include <string>
26#include <utility>
27#include <vector>
28
29namespace Gaudi {
30 namespace Details {
31
32 template <typename T>
33 constexpr bool is_gaudi_property_v = false;
34
35 template <typename TYPE, typename VERIFIER, typename HANDLERS>
37
38 } // namespace Details
39 namespace Utils {
41 inline bool iequal( std::string_view v1, std::string_view v2 ) {
42 return std::equal( begin( v1 ), end( v1 ), begin( v2 ), end( v2 ),
43 []( char c1, char c2 ) { return toupper( c1 ) == toupper( c2 ); } );
44 }
45 } // namespace Utils
46} // namespace Gaudi
67template <class BASE>
68class GAUDI_API PropertyHolder : public BASE {
69 static_assert( std::is_base_of_v<IProperty, BASE> && std::is_base_of_v<INamedInterface, BASE>,
70 "PropertyHolder template argument must inherit from IProperty and INamedInterface" );
71
72public:
80
81 PropertyHolder() = default;
82
85 PropertyHolder( const PropertyHolder& ) = delete;
88
89public:
93 assertUniqueName( prop.name() );
94 m_properties.push_back( &prop );
95 return prop;
96 }
97
100 template <typename TYPE>
102 Gaudi::Details::PropertyBase* declareProperty( const std::string& name, TYPE& value,
103 const std::string& doc = "none" ) {
104 auto make_property = [&]( const std::string& n, TYPE& v ) {
105 if constexpr ( requires { typename TYPE::PropertyType; } ) {
106 return std::make_unique<typename TYPE::PropertyType>( n, v );
107 } else {
108 return std::make_unique<Gaudi::Property<TYPE&>>( n, v );
109 }
110 };
111 m_todelete.push_back( make_property( name, value ) );
113
114 p->setDocumentation( doc );
115 return &declareProperty( *p );
116 }
117
120 template <class TYPE, class VERIFIER, class HANDLERS>
123 const std::string& doc = "none" ) {
125 p->setName( name );
126
127 p->setDocumentation( doc );
128 return &declareProperty( *p );
129 }
130
134 const std::string& rname = "" ) {
135 if ( !rsvc ) return nullptr;
136 const std::string& nam = rname.empty() ? name : rname;
138 m_remoteProperties.emplace_back( RemProperty{ name, rsvc, nam } );
139 return p;
140 }
141
143
144 // ==========================================================================
145 // IProperty implementation
146 // ==========================================================================
151 StatusCode setProperty( const std::string& name, const Gaudi::Details::PropertyBase& p ) override {
153 if ( pp && pp->assign( p ) ) return StatusCode::SUCCESS;
154 return StatusCode::FAILURE;
155 }
156
159 StatusCode setProperty( const std::string& s ) override {
160 std::string name;
161 std::string value;
162 StatusCode sc = Gaudi::Parsers::parse( name, value, s );
163 if ( sc.isFailure() ) return sc;
164 return setPropertyRepr( name, value );
165 }
166
169 StatusCode setPropertyRepr( const std::string& n, const std::string& r ) override {
170 try {
173 return ( p && p->fromString( r ) ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
174 } catch ( const std::invalid_argument& err ) {
175 throw GaudiException{ "error setting property " + n, this->name(), StatusCode::FAILURE, err };
176 }
177 }
178
182 try {
183 const Gaudi::Details::PropertyBase* pp = property( p->name() );
184 if ( pp && pp->load( *p ) ) return StatusCode::SUCCESS;
185 } catch ( ... ) {}
186 return StatusCode::FAILURE;
187 }
188
191 const Gaudi::Details::PropertyBase& getProperty( std::string_view name ) const override {
192 const Gaudi::Details::PropertyBase* p = property( name );
193 if ( !p ) throw std::out_of_range( "Property " + std::string{ name } + " not found." );
194 return *p;
195 }
196
199 StatusCode getProperty( std::string_view n, std::string& v ) const override {
200 // get the property
202 if ( !p ) return StatusCode::FAILURE;
203 // convert the value into the string
204 v = p->toString();
205 return StatusCode::SUCCESS;
206 }
207
210 const std::vector<Gaudi::Details::PropertyBase*>& getProperties() const override { return m_properties; }
214 bool hasProperty( std::string_view name ) const override {
215 return any_of( begin( m_properties ), end( m_properties ),
216 [&name]( const Gaudi::Details::PropertyBase* prop ) {
217 return Gaudi::Utils::iequal( prop->name(), name );
218 } ) ||
219 any_of( begin( m_remoteProperties ), end( m_remoteProperties ),
220 [&name]( const auto& prop ) { return Gaudi::Utils::iequal( prop.name, name ); } );
221 }
222
223 // get local or remote property by name
224 Gaudi::Details::PropertyBase* property( std::string_view name ) const {
225 // local property ?
227 if ( lp ) return lp;
228 // look for remote property
229 for ( const auto& it : m_remoteProperties ) {
230 if ( !Gaudi::Utils::iequal( it.name, name ) ) continue;
231 const IProperty* p = it.owner;
232 if ( !p ) continue;
233 return property( it.remName, p->getProperties() );
234 }
235 return nullptr;
236 }
237
239 auto set_prop = [&optsSvc, this]( auto prop ) { optsSvc.bind( this->name(), prop ); };
240 std::for_each( begin( m_properties ), end( m_properties ), set_prop );
241 std::for_each( begin( m_remoteProperties ), end( m_remoteProperties ), [&set_prop, this]( auto& rem ) {
242 if ( rem.owner ) set_prop( this->property( rem.remName, rem.owner->getProperties() ) );
243 } );
244 }
245
246private:
248 Gaudi::Details::PropertyBase* property( std::string_view name,
249 const std::vector<Gaudi::Details::PropertyBase*>& props ) const {
250 auto it = std::find_if( props.begin(), props.end(), [name]( Gaudi::Details::PropertyBase* p ) {
251 return p && Gaudi::Utils::iequal( p->name(), name );
252 } );
253 return ( it != props.end() ) ? *it : nullptr;
254 }
255
258 void assertUniqueName( std::string_view name ) const {
259 if ( hasProperty( name ) ) {
260 auto msgSvc = Gaudi::svcLocator()->service<IMessageSvc>( "MessageSvc" );
261 if ( !msgSvc ) std::cerr << "error: cannot get MessageSvc!" << std::endl;
262 MsgStream log( msgSvc, this->name() );
263 log << MSG::WARNING << "duplicated property name '" << name << "', see https://its.cern.ch/jira/browse/GAUDI-1023"
264 << endmsg;
265 }
266 }
267
268 typedef std::vector<Gaudi::Details::PropertyBase*> Properties;
269 struct RemProperty {
270 std::string name;
271 IProperty* owner = nullptr;
272 std::string remName;
273 };
274 typedef std::vector<RemProperty> RemoteProperties;
275
281 std::vector<std::unique_ptr<Gaudi::Details::PropertyBase>> m_todelete;
282};
void toupper(std::string &s)
#define GAUDI_API
Definition Kernel.h:49
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
void setDocumentation(std::string value)
set the documentation string
virtual std::string toString() const =0
value -> string
void setName(std::string value)
set the new value for the property name
virtual StatusCode fromString(const std::string &value)=0
string -> value
const std::string name() const
property name
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
Define general base for Gaudi exception.
The IMessage is the interface implemented by the message service.
Definition IMessageSvc.h:34
The IProperty is the basic interface for all components which have properties that can be set or get.
Definition IProperty.h:32
virtual const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const =0
Get list of properties.
StatusCode setProperty(const Gaudi::Details::PropertyBase &p)
Set the property from a property.
Definition IProperty.h:38
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
StatusCode getProperty(Gaudi::Details::PropertyBase *p) const override
get the property
PropertyHolder()=default
Gaudi::Details::PropertyBase * property(std::string_view name, const std::vector< Gaudi::Details::PropertyBase * > &props) const
get the property by name form the proposed list
std::vector< std::unique_ptr< Gaudi::Details::PropertyBase > > m_todelete
Properties owned by PropertyHolder, to be deleted.
const Gaudi::Details::PropertyBase & getProperty(std::string_view name) const override
get the property by name
Gaudi::Details::PropertyBase * property(std::string_view name) const
\fixme property and bindPropertiesTo should be protected
RemoteProperties m_remoteProperties
Collection of all declared remote properties.
void assertUniqueName(std::string_view name) const
Issue a runtime warning if the name is already present in the list of properties (see GAUDI-1023).
Properties m_properties
Collection of all declared properties.
PropertyHolder(const PropertyHolder &)=delete
StatusCode setPropertyRepr(const std::string &n, const std::string &r) override
set the property from name and value string representation
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.
StatusCode setProperty(const std::string &name, const Gaudi::Details::PropertyBase &p) override
set the property from another property with a different name
PropertyHolder< BASE > PropertyHolderImpl
Typedef used to refer to this class from derived classes, as in.
Gaudi::Details::PropertyBase * declareRemoteProperty(const std::string &name, IProperty *rsvc, const std::string &rname="")
Declare a remote property.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Details::PropertyBase &prop)
Declare a property.
StatusCode getProperty(std::string_view n, std::string &v) const override
convert the property to the string
StatusCode setProperty(const std::string &s) override
set the property from the formatted string
bool hasProperty(std::string_view name) const override
Return true if we have a property with the given name.
void bindPropertiesTo(Gaudi::Interfaces::IOptionsSvc &optsSvc)
std::vector< RemProperty > RemoteProperties
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.
const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const override
get all properties
PropertyHolder & operator=(const PropertyHolder &)=delete
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
constexpr bool is_gaudi_property_v
StatusCode parse(GaudiUtils::HashMap< K, V > &result, std::string_view input)
Basic parser for the types of HashMap used in DODBasicMapper.
bool iequal(std::string_view v1, std::string_view v2)
Helper for case insensitive string comparison.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
AttribStringParser::Iterator end(const AttribStringParser &)
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1
GAUDI_API ISvcLocator * svcLocator()
@ WARNING
Definition IMessageSvc.h:22
Interface for a component that manages application configuration options.
Definition IOptionsSvc.h:46
virtual void bind(const std::string &prefix, Gaudi::Details::PropertyBase *property)=0
Register a Gaudi::Property instance to the option service.