![]() |
|
|
Generated: 24 Nov 2008 |
00001 // $Id: Property.cpp,v 1.24 2007/09/25 10:31:43 marcocle Exp $ 00002 // ============================================================================ 00003 // CVS tag $Name: v26r0 $, verison $Revision: 1.24 $ 00004 // ============================================================================ 00005 // Include files 00006 // ============================================================================ 00007 // STD & STL 00008 // ============================================================================ 00009 #include <iostream> 00010 #include <stdexcept> 00011 #include <vector> 00012 #include <string> 00013 #include <utility> 00014 #include <map> 00015 #include <algorithm> 00016 #include <functional> 00017 // ============================================================================ 00018 // GaudiKernel 00019 // ============================================================================ 00020 #include "GaudiKernel/IProperty.h" 00021 #include "GaudiKernel/SmartIF.h" 00022 #include "GaudiKernel/Property.h" 00023 #include "GaudiKernel/PropertyCallbackFunctor.h" 00024 #include "GaudiKernel/GaudiHandle.h" 00025 // ============================================================================ 00026 // Boost 00027 // ============================================================================ 00028 #include "boost/algorithm/string/case_conv.hpp" 00029 // ============================================================================ 00035 // ============================================================================ 00036 // The output operator for friendly printout 00037 // ============================================================================ 00038 std::ostream& operator<<( std::ostream& stream , 00039 const Property& prop ) 00040 { return prop.fillStream ( stream ) ; } 00041 // ============================================================================ 00042 /* constructor from the property name and the type 00043 * @param name proeprty name 00044 * @param type property C++/RTTI type 00045 */ 00046 // ============================================================================ 00047 Property::Property 00048 ( const std::type_info& type , 00049 const std::string& name ) 00050 : m_name ( name ) 00051 , m_documentation ( name ) 00052 , m_typeinfo ( &type ) 00053 , m_readCallBack ( 0 ) 00054 , m_updateCallBack ( 0 ) 00055 {} 00056 // ============================================================================ 00057 /* constructor from the property name and the type 00058 * @param type property C++/RTTI type 00059 * @param name proeprty name 00060 */ 00061 // ============================================================================ 00062 Property::Property 00063 ( const std::string& name , 00064 const std::type_info& type ) 00065 : m_name ( name ) 00066 , m_documentation ( name ) 00067 , m_typeinfo ( &type ) 00068 , m_readCallBack ( 0 ) 00069 , m_updateCallBack ( 0 ) 00070 {} 00071 // ============================================================================ 00072 // copy contructor 00073 // ============================================================================ 00074 Property::Property 00075 ( const Property& right ) 00076 : m_name ( right.m_name ) 00077 , m_documentation ( right.m_documentation ) 00078 , m_typeinfo ( right.m_typeinfo ) 00079 , m_readCallBack ( 0 ) 00080 , m_updateCallBack ( 0 ) 00081 { 00082 if ( 0 != right.m_readCallBack ) 00083 { m_readCallBack = right.m_readCallBack -> clone () ; } 00084 if ( 0 != right.m_updateCallBack ) 00085 { m_updateCallBack = right.m_updateCallBack -> clone () ; } 00086 } 00087 // ============================================================================ 00088 // Assignement 00089 // ============================================================================ 00090 Property& Property::operator=( const Property& right ) 00091 { 00092 if ( &right == this ) { return *this ; } 00093 // 00094 m_name = right.m_name ; 00095 m_documentation = right.m_documentation ; 00096 m_typeinfo = right.m_typeinfo ; 00097 // 00098 if ( 0 != m_readCallBack ) 00099 { delete m_readCallBack ; m_readCallBack = 0 ; } 00100 if ( 0 != m_updateCallBack ) 00101 { delete m_updateCallBack ; m_updateCallBack = 0 ; } 00102 if ( 0 != right.m_readCallBack ) 00103 { m_readCallBack = right.m_readCallBack -> clone () ; } 00104 if ( 0 != right.m_updateCallBack ) 00105 { m_updateCallBack = right.m_updateCallBack -> clone () ; } 00106 // 00107 return *this ; 00108 } 00109 // ============================================================================ 00110 // virtual destructor 00111 // ============================================================================ 00112 Property::~Property() 00113 { 00114 if ( 0 != m_readCallBack ) 00115 { delete m_readCallBack ; m_readCallBack = 0 ; } 00116 if ( 0 != m_updateCallBack ) 00117 { delete m_updateCallBack ; m_updateCallBack = 0 ; } 00118 } 00119 // ============================================================================ 00120 // Call-back functor at reading: the functor is ownered by property! 00121 // ============================================================================ 00122 const PropertyCallbackFunctor* Property::readCallBack () const 00123 { return m_readCallBack ; } 00124 // ============================================================================ 00125 // Call-back functor for update: the funtor is ownered by property! 00126 // ============================================================================ 00127 const PropertyCallbackFunctor* Property::updateCallBack () const 00128 { return m_updateCallBack ; } 00129 // ============================================================================ 00130 // set new callback for reading 00131 // ============================================================================ 00132 void Property::declareReadHandler ( PropertyCallbackFunctor* pf ) 00133 { 00134 if ( 0 != m_readCallBack ) 00135 { delete m_readCallBack ; m_readCallBack = 0 ; } 00136 m_readCallBack = pf ; 00137 } 00138 // ============================================================================ 00139 // set new callback for update 00140 // ============================================================================ 00141 void Property::declareUpdateHandler ( PropertyCallbackFunctor* pf ) 00142 { 00143 if ( 0 != m_updateCallBack ) 00144 { delete m_updateCallBack ; m_updateCallBack = 0 ; } 00145 m_updateCallBack = pf ; 00146 } 00147 // ============================================================================ 00148 // use the call-back function at reading 00149 // ============================================================================ 00150 void Property::useReadHandler () const 00151 { 00152 if ( 0 == m_readCallBack ) { return ; } // RETURN 00153 const Property& p = *this ; 00154 PropertyCallbackFunctor* theCallBack = m_readCallBack; 00155 // avoid infinite loop 00156 m_readCallBack = 0; 00157 (*theCallBack)( const_cast<Property&>(p) ) ; 00158 m_readCallBack = theCallBack; 00159 } 00160 // ============================================================================ 00161 // use the call-back function at update 00162 // ============================================================================ 00163 void Property::useUpdateHandler () 00164 { 00165 if ( 0 == m_updateCallBack ) { return ; } // RETURN 00166 PropertyCallbackFunctor* theCallBack = m_updateCallBack; 00167 // avoid infinite loop 00168 m_updateCallBack = 0; 00169 (*theCallBack)( *this ) ; 00170 m_updateCallBack = theCallBack; 00171 } 00172 // ============================================================================ 00173 // the printout of the property value 00174 // ============================================================================ 00175 std::ostream& 00176 Property::fillStream ( std::ostream& stream ) const 00177 { return stream << " '" <<name() << "':" << toString() ; } 00178 // ============================================================================ 00179 /* simple function which check the existence of the property with 00180 * the given name. 00181 * 00182 * @code 00183 * 00184 * IInterface* p = . 00185 * 00186 * const bool = hasProperty( p , "Context" ) ; 00187 * 00188 * @endcode 00189 * 00190 * @param p pointer to IInterface object (any component) 00191 * @param name property name (case insensitive) 00192 * @return true if "p" has a property with such name 00193 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00194 * @date 2006-09-09 00195 */ 00196 // ============================================================================ 00197 bool Gaudi::Utils::hasProperty 00198 ( const IInterface* p , 00199 const std::string& name ) 00200 { 00201 // trivial check 00202 if ( 0 == p ) { return false ; } // RETURN 00203 // gelegate to another method 00204 return 0 != getProperty ( p , name ) ; 00205 } 00206 // ============================================================================ 00207 /* simple function which check the existence of the property with 00208 * the given name. 00209 * 00210 * @code 00211 * 00212 * const IProperty* p = ... ; 00213 * 00214 * const bool = hasProperty( p , "Context" ) ; 00215 * 00216 * @endcode 00217 * 00218 * @param p pointer to IProperty object 00219 * @param name property name (case insensitive) 00220 * @return true if "p" has a property with such name 00221 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00222 * @date 2006-09-09 00223 */ 00224 // ============================================================================ 00225 bool Gaudi::Utils::hasProperty 00226 ( const IProperty* p , 00227 const std::string& name ) 00228 { 00229 if ( 0 == p ) { return false ; } 00230 // delegate the actual work to another method ; 00231 return 0 != getProperty ( p , name ) ; 00232 } 00233 // ============================================================================ 00234 // 00235 // GaudiHandleProperty implementation 00236 // 00237 GaudiHandleProperty::GaudiHandleProperty 00238 ( const std::string& name, GaudiHandleBase& ref ) 00239 : Property( name, typeid( GaudiHandleBase ) ), m_pValue( &ref ) 00240 { 00241 m_pValue->setPropertyName( name ); 00242 } 00243 00244 bool GaudiHandleProperty::setValue( const GaudiHandleBase& value ) { 00245 m_pValue->setTypeAndName( value.typeAndName() ); 00246 useUpdateHandler(); 00247 return true; 00248 } 00249 00250 std::string GaudiHandleProperty::toString( ) const { 00251 useReadHandler(); 00252 return m_pValue->typeAndName(); 00253 } 00254 00255 StatusCode GaudiHandleProperty::fromString( const std::string& s) { 00256 m_pValue->setTypeAndName( s ); 00257 useUpdateHandler(); 00258 return StatusCode::SUCCESS; 00259 } 00260 00261 00262 // 00263 // GaudiHandlePropertyArray implementation 00264 // 00265 GaudiHandleArrayProperty::GaudiHandleArrayProperty( const std::string& name, GaudiHandleArrayBase& ref ) 00266 : Property( name, typeid( GaudiHandleArrayBase ) ), m_pValue( &ref ) 00267 { 00268 m_pValue->setPropertyName( name ); 00269 } 00270 00271 bool GaudiHandleArrayProperty::setValue( const GaudiHandleArrayBase& value ) { 00272 m_pValue->setTypesAndNames( value.typesAndNames() ); 00273 useUpdateHandler(); 00274 return true; 00275 } 00276 00277 std::string GaudiHandleArrayProperty::toString() const { 00278 // treat as if a StringArrayProperty 00279 useReadHandler(); 00280 return Gaudi::Utils::toString( m_pValue->typesAndNames() ); 00281 } 00282 00283 StatusCode GaudiHandleArrayProperty::fromString( const std::string& source ) { 00284 // treat as if a StringArrayProperty 00285 std::vector< std::string > tmp; 00286 StatusCode sc = Gaudi::Parsers::parse ( tmp , source ); 00287 if ( sc.isFailure() ) return sc; 00288 if ( !m_pValue->setTypesAndNames( tmp ) ) return StatusCode::FAILURE; 00289 useUpdateHandler(); 00290 return StatusCode::SUCCESS; 00291 } 00292 00293 00294 00295 // ============================================================================ 00296 namespace 00297 { 00298 // get the property by name (case insensitive) 00299 struct _ByName_ : public std::unary_function<const Property*,bool> 00300 { 00302 _ByName_ ( const std::string& name ) 00303 : m_name ( boost::algorithm::to_lower_copy( name ) ) {} 00305 bool operator () ( const Property* p ) const 00306 { 00307 if ( 0 == p ) { return false ; } 00308 return m_name == boost::algorithm::to_lower_copy( p->name() ) ; 00309 } ; 00310 protected: 00311 _ByName_(); 00312 private: 00313 std::string m_name ; 00314 } ; 00315 } 00316 // ============================================================================ 00317 /* simple function which gets the property with given name 00318 * from the component 00319 * 00320 * @code 00321 * 00322 * const IProperty* p = ... ; 00323 * 00324 * const Property* pro = getProperty( p , "Context" ) ; 00325 * 00326 * @endcode 00327 * 00328 * @param p pointer to IProperty object 00329 * @param name property name (case insensitive) 00330 * @return property with the given name (if exists), NULL otherwise 00331 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00332 * @date 2006-09-09 00333 */ 00334 // ============================================================================ 00335 Property* Gaudi::Utils::getProperty 00336 ( const IProperty* p , 00337 const std::string& name ) 00338 { 00339 // trivial check 00340 if ( 0 == p ) { return 0 ; } // RETURN 00341 // get all properties 00342 typedef std::vector<Property*> List ; 00343 const List& lst = p->getProperties() ; 00344 if ( lst.empty() ) { return 0 ; } // RETURN 00345 // comparison criteria: 00346 List::const_iterator ifound = 00347 std::find_if ( lst.begin() , lst.end() , _ByName_( name ) ) ; 00348 if ( lst.end() == ifound ) { return 0 ; } // RETURN 00349 // OK 00350 return *ifound ; 00351 } 00352 // ============================================================================ 00353 /* simple function which gets the property with given name 00354 * from the component 00355 * 00356 * @code 00357 * 00358 * const IInterface* p = ... ; 00359 * 00360 * const Property* pro = getProperty( p , "Context" ) ; 00361 * 00362 * @endcode 00363 * 00364 * @param p pointer to IInterface object 00365 * @param name property name (case insensitive) 00366 * @return property with the given name (if exists), NULL otherwise 00367 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00368 * @date 2006-09-09 00369 */ 00370 // ============================================================================ 00371 Property* Gaudi::Utils::getProperty 00372 ( const IInterface* p , const std::string& name ) 00373 { 00374 // trivial check 00375 if ( 0 == p ) { return 0 ; } // RETURN 00376 // remove const-qualifier 00377 IInterface* _i = const_cast<IInterface*>( p ) ; 00378 if ( 0 == _i ) { return 0 ; } // RETURN 00379 SmartIF<IProperty> property ( _i ) ; 00380 if ( !property ) { return 0 ; } // RETURN 00381 return getProperty ( property , name ) ; 00382 } 00383 // ============================================================================ 00384 /* check the property by name from the list of the properties 00385 * 00386 * @code 00387 * 00388 * IJobOptionsSvc* svc = ... ; 00389 * 00390 * const std::string client = ... ; 00391 * 00392 * // get the property: 00393 * bool context = 00394 * hasProperty ( svc->getProperties( client ) , "Context" ) 00395 * 00396 * @endcode 00397 * 00398 * @see IJobOptionsSvc 00399 * 00400 * @param p list of properties 00401 * @param name property name (case insensitive) 00402 * @return true if the property exists 00403 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00404 * @date 2006-09-09 00405 */ 00406 // ============================================================================ 00407 bool Gaudi::Utils::hasProperty 00408 ( const std::vector<const Property*>* p , 00409 const std::string& name ) 00410 { 00411 // delegate to another method 00412 return 0 != getProperty ( p , name ) ; 00413 } 00414 // ============================================================================ 00415 /* get the property by name from the list of the properties 00416 * 00417 * @code 00418 * 00419 * IJobOptionsSvc* svc = ... ; 00420 * 00421 * const std::string client = ... ; 00422 * 00423 * // get the property: 00424 * const Property* context = 00425 * getProperty ( svc->getProperties( client ) , "Context" ) 00426 * 00427 * @endcode 00428 * 00429 * @see IJobOptionsSvc 00430 * 00431 * @param p list of properties 00432 * @param name property name (case insensitive) 00433 * @return property with the given name (if exists), NULL otherwise 00434 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00435 * @date 2006-09-09 00436 */ 00437 // ============================================================================ 00438 const Property* Gaudi::Utils::getProperty 00439 ( const std::vector<const Property*>* p , 00440 const std::string& name ) 00441 { 00442 // trivial check 00443 if ( 0 == p ) { return 0 ; } // RETURN 00444 std::vector<const Property*>::const_iterator ifound = 00445 std::find_if ( p->begin() , p->end() , _ByName_( name ) ) ; 00446 if ( p->end() == ifound ) { return 0 ; } // RETURN 00447 // OK 00448 return *ifound ; 00449 } 00450 // ============================================================================ 00451 /* the full specialization of the 00452 * method setProperty( IProperty, std::string, const TYPE&) 00453 * for C-strings 00454 * 00455 * @param component component which needs to be configured 00456 * @param name name of the property 00457 * @param value value of the property 00458 * @param doc the new documentation string 00459 * 00460 * @see IProperty 00461 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00462 * @date 2007-05-13 00463 */ 00464 // ============================================================================ 00465 StatusCode Gaudi::Utils::setProperty 00466 ( IProperty* component , 00467 const std::string& name , 00468 const char* value , 00469 const std::string& doc ) 00470 { 00471 const std::string val = std::string( value ) ; 00472 return Gaudi::Utils::setProperty ( component , name , val , doc ) ; 00473 } 00474 // ============================================================================ 00475 /* the full specialization of the 00476 * method Gaudi::Utils::setProperty( IProperty, std::string, const TYPE&) 00477 * for standard strings 00478 * 00479 * @param component component which needs to be configured 00480 * @param name name of the property 00481 * @param value value of the property 00482 * 00483 * @see IProperty 00484 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00485 * @date 2007-05-13 00486 */ 00487 // ============================================================================ 00488 StatusCode Gaudi::Utils::setProperty 00489 ( IProperty* component , 00490 const std::string& name , 00491 const std::string& value , 00492 const std::string& doc ) 00493 { 00494 if ( 0 == component ) { return StatusCode::FAILURE ; } // RETURN 00495 if ( !hasProperty ( component , name ) ) { return StatusCode::FAILURE ; } 00496 StatusCode sc = component -> setProperty ( name , value ) ; 00497 if ( !doc.empty() ) 00498 { 00499 Property* p = getProperty( component , name ) ; 00500 if ( 0 != p ) { p -> setDocumentation ( doc ) ; } 00501 } 00502 sc.ignore() ; 00503 return sc ; 00504 } 00505 // ============================================================================ 00506 /* simple function to set the property of the given object from another 00507 * property 00508 * 00509 * @code 00510 * 00511 * IProperty* component = ... ; 00512 * 00513 * const Property* prop = ... ; 00514 * StatusCode sc = setProperty ( component , "Data" , prop ) ; 00515 * 00516 * @endcode 00517 * 00518 * @param component component which needs to be configured 00519 * @param name name of the property 00520 * @param property the property 00521 * @param doc the new documentation string 00522 * 00523 * @see IProperty 00524 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00525 * @date 2007-05-13 00526 */ 00527 // ============================================================================ 00528 StatusCode Gaudi::Utils::setProperty 00529 ( IProperty* component , 00530 const std::string& name , 00531 const Property* property , 00532 const std::string& doc ) 00533 { 00534 if ( 0 == component || 0 == property ) { return StatusCode::FAILURE ; } 00535 if ( !hasProperty ( component , name ) ) { return StatusCode::FAILURE ; } 00536 Property* p = getProperty ( component , name ) ; 00537 if ( 0 == p ) { return StatusCode::FAILURE ; } 00538 if ( !p->assign ( *property ) ) { return StatusCode::FAILURE ; } 00539 if ( !doc.empty() ) { p->setDocumentation( doc ) ; } 00540 return StatusCode::SUCCESS ; 00541 } 00542 // ============================================================================ 00543 /* simple function to set the property of the given object from another 00544 * property 00545 * 00546 * @code 00547 * 00548 * IProperty* component = ... ; 00549 * 00550 * const Property& prop = ... ; 00551 * StatusCode sc = setProperty ( component , "Data" , prop ) ; 00552 * 00553 * @endcode 00554 * 00555 * @param component component which needs to be configured 00556 * @param name name of the property 00557 * @param property the property 00558 * @param doc the new documentation string 00559 * 00560 * @see IProperty 00561 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00562 * @date 2007-05-13 00563 */ 00564 // ============================================================================ 00565 StatusCode Gaudi::Utils::setProperty 00566 ( IProperty* component , 00567 const std::string& name , 00568 const Property& property , 00569 const std::string& doc ) 00570 { return setProperty ( component , name , &property , doc ) ; } 00571 // ============================================================================ 00572 /* the full specialization of the 00573 * method setProperty( IInterface , std::string, const TYPE&) 00574 * for standard strings 00575 * 00576 * @param component component which needs to be configured 00577 * @param name name of the property 00578 * @param value value of the property 00579 * @param doc the new documentation string 00580 * 00581 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00582 * @date 2007-05-13 00583 */ 00584 // ============================================================================ 00585 StatusCode Gaudi::Utils::setProperty 00586 ( IInterface* component , 00587 const std::string& name , 00588 const std::string& value , 00589 const std::string& doc ) 00590 { 00591 if ( 0 == component ) { return StatusCode::FAILURE ; } 00592 SmartIF<IProperty> property ( component ) ; 00593 if ( !property ) { return StatusCode::FAILURE ; } 00594 return setProperty ( property , name , value , doc ) ; 00595 } 00596 // ============================================================================ 00597 /* the full specialization of the 00598 * method setProperty( IInterface , std::string, const TYPE&) 00599 * for C-strings 00600 * 00601 * @param component component which needs to be configured 00602 * @param name name of the property 00603 * @param value value of the property 00604 * @param doc the new documentation string 00605 * 00606 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00607 * @date 2007-05-13 00608 */ 00609 // ============================================================================ 00610 StatusCode Gaudi::Utils::setProperty 00611 ( IInterface* component , 00612 const std::string& name , 00613 const char* value , 00614 const std::string& doc ) 00615 { 00616 const std::string val = std::string( value ) ; 00617 return setProperty ( component , name , val , doc ) ; 00618 } 00619 // ============================================================================ 00620 /* simple function to set the property of the given object from another 00621 * property 00622 * 00623 * @code 00624 * 00625 * IInterface* component = ... ; 00626 * 00627 * const Property* prop = ... ; 00628 * StatusCode sc = setProperty ( component , "Data" , prop ) ; 00629 * 00630 * @endcode 00631 * 00632 * @param component component which needs to be configured 00633 * @param name name of the property 00634 * @param property the property 00635 * @param doc the new documentation string 00636 * 00637 * @see IProperty 00638 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00639 * @date 2007-05-13 00640 */ 00641 // ============================================================================ 00642 StatusCode Gaudi::Utils::setProperty 00643 ( IInterface* component , 00644 const std::string& name , 00645 const Property* property , 00646 const std::string& doc ) 00647 { 00648 if ( 0 == component ) { return StatusCode::FAILURE ; } 00649 SmartIF<IProperty> prop ( component ) ; 00650 if ( !prop ) { return StatusCode::FAILURE ; } 00651 return setProperty ( prop , name , property , doc ) ; 00652 } 00653 // ============================================================================ 00654 /* simple function to set the property of the given object from another 00655 * property 00656 * 00657 * @code 00658 * 00659 * IInterface* component = ... ; 00660 * 00661 * const Property& prop = ... ; 00662 * StatusCode sc = setProperty ( component , "Data" , prop ) ; 00663 * 00664 * @endcode 00665 * 00666 * @param component component which needs to be configured 00667 * @param name name of the property 00668 * @param property the property 00669 * @param doc the new documentation string 00670 * 00671 * @see IProperty 00672 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 00673 * @date 2007-05-13 00674 */ 00675 // ============================================================================ 00676 StatusCode Gaudi::Utils::setProperty 00677 ( IInterface* component , 00678 const std::string& name , 00679 const Property& property , 00680 const std::string& doc ) 00681 { return setProperty ( component , name , &property , doc ) ; } 00682 // ============================================================================ 00683 00684 00685 00686 00687 00688 // ============================================================================ 00689 // The END 00690 // ============================================================================ 00691