Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:34

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #ifndef GAUDIUTILS_GETDATA_H
0012 #define GAUDIUTILS_GETDATA_H 1
0013 // ============================================================================
0014 // Include files
0015 // ============================================================================
0016 // GaudiKernel
0017 // ============================================================================
0018 #include "GaudiKernel/IDataProviderSvc.h"
0019 #include "GaudiKernel/IMessageSvc.h"
0020 #include "GaudiKernel/IRegistry.h"
0021 #include "GaudiKernel/MsgStream.h"
0022 #include "GaudiKernel/SmartDataPtr.h"
0023 #include "GaudiKernel/StatusCode.h"
0024 // ============================================================================
0025 // GaudiUtils
0026 // ============================================================================
0027 #include "GaudiKernel/AnyDataWrapper.h"
0028 #include "GaudiKernel/NamedRange.h"
0029 #include "GaudiKernel/Range.h"
0030 // ============================================================================
0031 // Forward declaration
0032 // ============================================================================
0033 template <class BASE>
0034 class GaudiCommon; // GaudiAlg
0035 // ============================================================================
0036 namespace Gaudi {
0037   namespace Utils {
0038     // ========================================================================
0039     /** @struct _GetType
0040      *  Helper structure to define the proper return type for
0041      *  "get"-functions
0042      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0043      *  @date   2008-07-22
0044      */
0045     template <class TYPE>
0046     struct _GetType {
0047       typedef TYPE* return_type;
0048     };
0049     // ========================================================================
0050     /// the template specialization for pointers
0051     template <class TYPE>
0052     struct _GetType<TYPE*> {
0053       typedef TYPE* return_type;
0054     };
0055     // ========================================================================
0056     /// the template specialization for references
0057     template <class TYPE>
0058     struct _GetType<TYPE&> {
0059       typedef TYPE* return_type;
0060     };
0061     // ========================================================================
0062     /// the template specialization for "ranges"
0063     template <class CONTAINER>
0064     struct _GetType<Gaudi::Range_<CONTAINER>> {
0065       typedef Gaudi::Range_<CONTAINER> return_type;
0066     };
0067     // ========================================================================
0068     /// the template specialization for "named ranges"
0069     template <class CONTAINER>
0070     struct _GetType<Gaudi::NamedRange_<CONTAINER>> {
0071       typedef Gaudi::NamedRange_<CONTAINER> return_type;
0072     };
0073     // ========================================================================
0074     /** Helper function to provide the minimal lookup and cast functionality
0075      *  of SmartDataPtr used in the helper classes.
0076      *  This version is dealing with the general case, where AnyDataWrapper cannot be used
0077      */
0078     template <class TYPE, std::enable_if_t<!std::is_constructible_v<TYPE>, void*> = nullptr>
0079     typename _GetType<TYPE>::return_type getFromTS( IDataProviderSvc* service, std::string_view location ) {
0080       DataObject* obj = nullptr;
0081       // Return the casted pointer if the retrieve was successful or nullptr otherwise.
0082       return service->retrieveObject( location, obj ).isSuccess()
0083                  ? dynamic_cast<typename _GetType<TYPE>::return_type>( obj )
0084                  : nullptr;
0085     }
0086     // ========================================================================
0087     /** Helper function to provide the minimal lookup and cast functionality
0088      *  of SmartDataPtr used in the helper classes.
0089      *  This version allows the use of AnyDataWrapper but restricts to the case
0090      *  where TYPE is constructible
0091      */
0092     template <class TYPE, std::enable_if_t<std::is_constructible_v<TYPE>, void*> = nullptr>
0093     typename _GetType<TYPE>::return_type getFromTS( IDataProviderSvc* service, std::string_view location ) {
0094       DataObject* obj = nullptr;
0095       // Return the casted pointer if the retrieve was successful or nullptr otherwise.
0096       StatusCode sc = service->retrieveObject( location, obj );
0097       if ( sc.isFailure() ) return nullptr;
0098       auto tobj = dynamic_cast<typename _GetType<TYPE>::return_type>( obj );
0099       if ( !tobj ) {
0100         // try with AnyDataWrapper
0101         if ( auto tobj2 = dynamic_cast<AnyDataWrapper<TYPE>*>( obj ); tobj2 ) { tobj = &( tobj2->getData() ); }
0102       }
0103       return tobj;
0104     }
0105     // ========================================================================
0106     /** @struct GetData GaudiUtils/GetData.h
0107      *
0108      *  Helper structure for implementation of  "get"-functions for
0109      *  GaudiCommon<BASE>
0110      *
0111      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0112      *  @date   2008-07-22
0113      */
0114     template <class TYPE>
0115     struct GetData {
0116     public:
0117       // ======================================================================
0118       typedef TYPE Type;
0119       /// the actual return type
0120       typedef typename _GetType<Type>::return_type return_type;
0121       // ======================================================================
0122     public:
0123       // ======================================================================
0124       /** the only one essential method
0125        *  @param common the actual "worker"
0126        *  @param service pointer to Data Provider Service
0127        *  @param location location of objects in TES
0128        *  @param checkData whether to check if the pointer is valid before returning it
0129        *  @return the data
0130        */
0131       template <class COMMON>
0132       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string_view location,
0133                               const bool checkData = true ) const {
0134         // use Data Provider Service
0135         return_type obj = getFromTS<Type>( service, location );
0136         if ( checkData ) { // check the data
0137           common.Assert( obj, std::string{ "get():: No valid data at '" }.append( location ).append( "'" ) );
0138         }
0139         // debug printout
0140         if ( common.msgLevel( MSG::DEBUG ) ) {
0141           common.debug() << "The object of type '" << System::typeinfoName( typeid( obj ) ) << "' "
0142                          << ( obj ? "has been" : "could not be" ) << " retrieved from TS at address '" << location
0143                          << "'" << endmsg;
0144         }
0145         // return located data
0146         return obj;
0147         // ======================================================================
0148       }
0149     };
0150     // ========================================================================
0151     /// the template specialization for ranges
0152     template <class TYPE>
0153     struct GetData<Gaudi::Range_<std::vector<const TYPE*>>> {
0154     public:
0155       // ======================================================================
0156       /// the actual return type
0157       typedef Gaudi::Range_<std::vector<const TYPE*>> Type;
0158       typedef typename _GetType<Type>::return_type    return_type;
0159       // ======================================================================
0160     public:
0161       // ======================================================================
0162       /** the only one essential method
0163        *  @param common the actual "worker"
0164        *  @param service pointer to Data Provider Service
0165        *  @param location location of objects in TES
0166        *  @param checkData whether to check if the pointer is valid before returning it
0167        *  @return the data
0168        */
0169       template <class COMMON>
0170       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string_view location,
0171                               const bool checkData = true ) const {
0172         /// try to be efficient:
0173         /// 1. load object only once:
0174         DataObject* object = this->getData( service, std::string{ location } );
0175         if ( object ) {
0176           /// 2. try to get the selection
0177           typedef typename TYPE::Selection Selection_;
0178           const Selection_*                sel = dynamic_cast<Selection_*>( object );
0179           if ( sel ) {
0180             if ( common.msgLevel( MSG::DEBUG ) ) {
0181               common.debug() << "The object of type '" << System::typeinfoName( typeid( *object ) )
0182                              << "' has been retrieved from TS at address '" << location << "'" << endmsg;
0183             }
0184             return make_range( sel );
0185           }
0186           /// 3. try to get the container
0187           typedef typename TYPE::Container Container_;
0188           const Container_*                cnt = dynamic_cast<Container_*>( object );
0189           if ( cnt ) {
0190             if ( common.msgLevel( MSG::DEBUG ) ) {
0191               common.debug() << "The object of type '" << System::typeinfoName( typeid( *object ) )
0192                              << "' has been retrieved from TS at address '" << location << "'" << endmsg;
0193             }
0194             return make_range( cnt );
0195           }
0196           // no valid data
0197           if ( checkData )
0198             common.Assert( false, std::string{ "get():: No valid data at '" }.append( location ).append( "'" ) );
0199         }
0200         // no valid data
0201         if ( checkData ) common.Assert( false, std::string{ "get():: No data at '" }.append( location ).append( "'" ) );
0202         // the fictive return
0203         return return_type();
0204       }
0205       // ======================================================================
0206     public:
0207       // ======================================================================
0208       // create the range from the container
0209       return_type make_range( const typename TYPE::Container* cnt ) const {
0210         return 0 == cnt ? return_type() : make_range( cnt->begin(), cnt->end() );
0211       }
0212       // create the range from the selection
0213       return_type make_range( const typename TYPE::Selection* cnt ) const {
0214         return 0 == cnt ? return_type() : return_type( cnt->begin(), cnt->end() );
0215       }
0216       // ======================================================================
0217       /** get the data form transient store
0218        *  @param service   pointer to data provider service
0219        *  @param location  the location
0220        *  @return the object for TES
0221        */
0222       DataObject* getData( IDataProviderSvc* service, std::string location ) const {
0223         /// Try to be efficient
0224         SmartDataObjectPtr getter( SmartDataObjectPtr::ObjectLoader::access(), service, nullptr,
0225                                    std::move( location ) );
0226         return getter.accessData();
0227       }
0228       // ======================================================================
0229     private:
0230       // ======================================================================
0231       template <class ITERATOR>
0232       return_type make_range( ITERATOR first, ITERATOR last ) const {
0233         auto _begin = reinterpret_cast<typename return_type::const_iterator*>( &first );
0234         auto _end   = reinterpret_cast<typename return_type::const_iterator*>( &last );
0235         return return_type( *_begin, *_end );
0236       }
0237       // ======================================================================
0238     };
0239     // ========================================================================
0240     /// the template specialization for named ranges
0241     template <class TYPE>
0242     struct GetData<Gaudi::NamedRange_<std::vector<const TYPE*>>> {
0243     public:
0244       // ======================================================================
0245       /// the actual return type
0246       typedef Gaudi::NamedRange_<std::vector<const TYPE*>> Type;
0247       typedef typename _GetType<Type>::return_type         return_type;
0248       // ======================================================================
0249     public:
0250       // ======================================================================
0251       /** the only one essential method
0252        *  @param common the actual "worker"
0253        *  @param service pointer to Data Provider Service
0254        *  @param location location of objects in TES
0255        *  @param checkData whether to check if the pointer is valid before returning it
0256        *  @return the data
0257        */
0258       template <class COMMON>
0259       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string_view location,
0260                               const bool checkData = true ) const {
0261         return return_type( m_range( common, service, location, checkData ), std::string{ location } );
0262       }
0263       // ======================================================================
0264     public:
0265       // ======================================================================
0266       // create the range from the container
0267       return_type make_range( const typename TYPE::Container* cnt ) const {
0268         if ( !cnt ) { return return_type(); }
0269         static const std::string s_empty = "";
0270         const IRegistry*         reg     = cnt->registry();
0271         return return_type( m_range.make_range( cnt ), reg ? reg->identifier() : s_empty );
0272       }
0273       // create the range from the selection
0274       return_type make_range( const typename TYPE::Selection* cnt ) const {
0275         if ( !cnt ) { return return_type(); }
0276         static const std::string s_empty = "";
0277         const IRegistry*         reg     = cnt->registry();
0278         return return_type( m_range.make_range( cnt ), reg ? reg->identifier() : s_empty );
0279       }
0280       // ======================================================================
0281       /** get the data form transient store
0282        *  @param service   pointer to data provider service
0283        *  @param location  the location
0284        *  @return the object for TES
0285        */
0286       DataObject* getData( IDataProviderSvc* service, std::string location ) const {
0287         return m_range.getData( service, std::move( location ) );
0288       }
0289       // ======================================================================
0290     private:
0291       /// =====================================================================
0292       /// the actual processor
0293       GetData<Gaudi::Range_<std::vector<const TYPE*>>> m_range;
0294       // ======================================================================
0295     };
0296     // ========================================================================
0297     /// the template specialization for const types
0298     template <class TYPE>
0299     struct GetData<const TYPE> : public GetData<TYPE> {};
0300     // ========================================================================
0301     /// the template specialization for pointer types
0302     template <class TYPE>
0303     struct GetData<TYPE*> : public GetData<TYPE> {};
0304     // ========================================================================
0305     /// the template specialization for reference types
0306     template <class TYPE>
0307     struct GetData<TYPE&> : public GetData<TYPE> {};
0308     // ========================================================================
0309     /** @struct CheckData  GaudiAlg/GetData.h
0310      *
0311      *  Helper structure for implementation of  "exists"-functions for
0312      *  GaudiCommon<BASE>
0313      *
0314      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0315      *  @date   2008-07-22
0316      */
0317     template <class TYPE>
0318     struct CheckData {
0319     public:
0320       // ======================================================================
0321       /** the only one essential method
0322        *  @param common the actual "worker"
0323        *  @param service pointer to Data Provider Service
0324        *  @param location location of objects in TES
0325        *  @return true for valid data
0326        */
0327       bool operator()( IDataProviderSvc* service, std::string_view location ) const {
0328         /// use Data Provider Service
0329         return getFromTS<TYPE>( service, location );
0330       }
0331       // ======================================================================
0332     };
0333     // ========================================================================
0334     /// the template specialization for ranges
0335     template <class TYPE>
0336     struct CheckData<Gaudi::Range_<std::vector<const TYPE*>>> {
0337     public:
0338       // ======================================================================
0339       /** the only one essential method
0340        *  @param common the actual "worker"
0341        *  @param service pointer to Data Provider Service
0342        *  @param location location of objects in TES
0343        *  @return true for valid data
0344        */
0345       bool operator()( IDataProviderSvc* service, std::string location ) const {
0346         DataObject* object = this->getData( service, std::move( location ) );
0347         return object && ( dynamic_cast<typename TYPE::Selection*>( object ) ||
0348                            dynamic_cast<typename TYPE::Container*>( object ) );
0349       }
0350       // ======================================================================
0351     protected:
0352       // ======================================================================
0353       /** get the data form transient store
0354        *  @param service   pointer to data provider service
0355        *  @param location  the location
0356        *  @return the object for TES
0357        */
0358       DataObject* getData( IDataProviderSvc* service, std::string location ) const {
0359         /// Try to be efficient
0360         SmartDataObjectPtr getter( SmartDataObjectPtr::ObjectLoader::access(), service, nullptr,
0361                                    std::move( location ) );
0362         return getter.accessData();
0363       }
0364       // ======================================================================
0365     };
0366     // ========================================================================
0367     /// the template specialization for ranges
0368     template <class TYPE>
0369     struct CheckData<Gaudi::NamedRange_<std::vector<const TYPE*>>>
0370         : public CheckData<Gaudi::Range_<std::vector<const TYPE*>>> {};
0371     // ========================================================================
0372     /// the template specialization for pointer types
0373     template <class TYPE>
0374     struct CheckData<TYPE*> : public CheckData<TYPE> {};
0375     // ========================================================================
0376     /// the template specialization for reference types
0377     template <class TYPE>
0378     struct CheckData<TYPE&> : public CheckData<TYPE> {};
0379     // ========================================================================
0380     /// the template specialization for 'const'-type
0381     template <class TYPE>
0382     struct CheckData<const TYPE> : public CheckData<TYPE> {};
0383     // ========================================================================
0384     /** @struct GetOrCreateData GaudiUtils/GetData.h
0385      *
0386      *  Helper structure for implementation of  "getOrCreate"-functions for
0387      *  GaudiCommon<BASE>
0388      *
0389      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0390      *  @date   2008-07-22
0391      */
0392     template <class TYPE, class TYPE2>
0393     struct GetOrCreateData {
0394     private:
0395       // ======================================================================
0396       /// the actual data getter
0397       typedef GetData<TYPE> Getter; // the actual data getter
0398       // ======================================================================
0399     public:
0400       // ======================================================================
0401       typedef typename Getter::Type Type;
0402       /// the actual return type
0403       typedef typename Getter::return_type return_type;
0404       // ======================================================================
0405     public:
0406       // ======================================================================
0407       /** the only one essential method
0408        *  @param common the actual "worker"
0409        *  @param service pointer to Data Provider Service
0410        *  @param location location of objects in TES
0411        *  @return the data
0412        */
0413       template <class COMMON>
0414       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string_view location,
0415                               std::string_view location2 ) const {
0416         SmartDataPtr<TYPE> obj( service, std::string{ location } );
0417         if ( !obj ) {
0418           auto o = std::make_unique<TYPE2>();
0419           auto r = o.get();
0420           common.put( service, std::move( o ), location2 );
0421           if ( common.msgLevel( MSG::DEBUG ) ) {
0422             common.debug() << "The object of type '" << System::typeinfoName( typeid( *r ) )
0423                            << "' has been created from TS at address '" << location2 << "'" << endmsg;
0424           }
0425           return r;
0426         }
0427         auto ret = obj.ptr();
0428         /// check the data
0429         common.Assert( !( !ret ), std::string{ "get():: No valid data at '" }.append( location ).append( "\'" ) );
0430         if ( common.msgLevel( MSG::DEBUG ) ) {
0431           common.debug() << "The object of type '" << System::typeinfoName( typeid( *ret ) )
0432                          << "' has been retrieved from TS at address '" << location << "'" << endmsg;
0433         }
0434         // return *VALID* data
0435         return ret;
0436         // ====================================================================
0437       }
0438     };
0439     // ========================================================================
0440     template <class TYPE, class TYPE2>
0441     struct GetOrCreateData<Gaudi::Range_<std::vector<const TYPE*>>, TYPE2> {
0442     private:
0443       // ======================================================================
0444       typedef Gaudi::Range_<std::vector<const TYPE*>> Range;
0445       /// the actual data getter
0446       typedef GetData<Range> Getter; //  the actual data getter
0447       /// the actual data checker
0448       typedef CheckData<Range> Checker; // the actual data checker
0449       // ======================================================================
0450     public:
0451       // ======================================================================
0452       typedef typename Getter::Type Type;
0453       /// the actual return type
0454       typedef typename Getter::return_type return_type;
0455       // ======================================================================
0456     public:
0457       // ======================================================================
0458       /** the only one essential method
0459        *  @param common the actual "worker"
0460        *  @param service pointer to Data Provider Service
0461        *  @param location location of objects in TES
0462        *  @return the data
0463        */
0464       template <class COMMON>
0465       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string_view location,
0466                               std::string_view location2 ) const {
0467         DataObject* obj = m_getter.getData( service, std::string{ location } );
0468         if ( !obj ) {
0469           common.put( service, std::make_unique<TYPE2>(), location2 );
0470           if ( common.msgLevel( MSG::DEBUG ) ) {
0471             common.debug() << "The object of type '" << System::typeinfoName( typeid( TYPE2 ) )
0472                            << "' has been created from TS at address '" << location2 << "'" << endmsg;
0473           }
0474         }
0475         return m_getter( common, service, location );
0476         // ====================================================================
0477       }
0478       // ======================================================================
0479     private:
0480       // ======================================================================
0481       /// the actual data getter
0482       Getter m_getter; // the actual data getter
0483       // ======================================================================
0484     };
0485     // ========================================================================
0486     template <class TYPE, class TYPE2>
0487     struct GetOrCreateData<Gaudi::NamedRange_<std::vector<const TYPE*>>, TYPE2> {
0488     private:
0489       // ======================================================================
0490       typedef Gaudi::NamedRange_<std::vector<const TYPE*>> Range;
0491       typedef Gaudi::Range_<std::vector<const TYPE*>>      Range_;
0492       typedef GetOrCreateData<Range_, TYPE2>               Helper;
0493       /// the actual data getter
0494       typedef GetData<Range> Getter; //  the actual data getter
0495       // ======================================================================
0496     public:
0497       // ======================================================================
0498       typedef typename Getter::Type Type;
0499       /// the actual return type
0500       typedef typename Getter::return_type return_type;
0501       // ======================================================================
0502     public:
0503       // ======================================================================
0504       /** the only one essential method
0505        *  @param common the actual "worker"
0506        *  @param service pointer to Data Provider Service
0507        *  @param location location of objects in TES
0508        *  @return the data
0509        */
0510       template <class COMMON>
0511       return_type operator()( const COMMON& common, IDataProviderSvc* service, std::string location,
0512                               std::string_view location2 ) const {
0513         auto range = m_range( common, service, location, location2 );
0514         return return_type( std::move( range ), std::move( location ) );
0515       }
0516       // ======================================================================
0517     private:
0518       // ======================================================================
0519       /// the actual data getter
0520       Helper m_range; // the actual data getter
0521       // ======================================================================
0522     };
0523     // ========================================================================
0524     template <class TYPE, class TYPE2>
0525     struct GetOrCreateData<TYPE, TYPE2*> : public GetOrCreateData<TYPE, TYPE2> {};
0526     template <class TYPE, class TYPE2>
0527     struct GetOrCreateData<TYPE*, TYPE2> : public GetOrCreateData<TYPE, TYPE2> {};
0528     template <class TYPE, class TYPE2>
0529     struct GetOrCreateData<TYPE*, TYPE2*> : public GetOrCreateData<TYPE, TYPE2> {};
0530     // ========================================================================
0531     template <class TYPE, class TYPE2>
0532     struct GetOrCreateData<TYPE, const TYPE2> : public GetOrCreateData<TYPE, TYPE2> {};
0533     template <class TYPE, class TYPE2>
0534     struct GetOrCreateData<const TYPE, TYPE2> : public GetOrCreateData<TYPE, TYPE2> {};
0535     template <class TYPE, class TYPE2>
0536     struct GetOrCreateData<const TYPE, const TYPE2> : public GetOrCreateData<TYPE, TYPE2> {};
0537     // ========================================================================
0538     template <class TYPE, class TYPE2>
0539     struct GetOrCreateData<TYPE, TYPE2&> : public GetOrCreateData<TYPE, TYPE2> {};
0540     template <class TYPE, class TYPE2>
0541     struct GetOrCreateData<TYPE&, TYPE2> : public GetOrCreateData<TYPE, TYPE2> {};
0542     template <class TYPE, class TYPE2>
0543     struct GetOrCreateData<TYPE&, TYPE2&> : public GetOrCreateData<TYPE, TYPE2> {};
0544     // ========================================================================
0545   } // namespace Utils
0546   // ==========================================================================
0547 } //                                                     end of namespace Gaudi
0548 // ============================================================================
0549 //                                                                      The END
0550 // ============================================================================
0551 #endif // GAUDIUTILS_GETDATA_H