Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-09-12 09:59:50

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWItemAccessorFactory
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Sat Oct 18 14:48:14 EDT 2008
0011 //
0012 
0013 // system include files
0014 #include <iostream>
0015 #include "TClass.h"
0016 #include "TVirtualCollectionProxy.h"
0017 #include "FWCore/Reflection/interface/TypeWithDict.h"
0018 #include "FWCore/Reflection/interface/MemberWithDict.h"
0019 
0020 // user include files
0021 #include "Fireworks/Core/interface/FWItemAccessorFactory.h"
0022 #include "Fireworks/Core/interface/FWItemAccessorRegistry.h"
0023 #include "Fireworks/Core/src/FWItemTVirtualCollectionProxyAccessor.h"
0024 #include "Fireworks/Core/interface/FWItemSingleAccessor.h"
0025 #include "Fireworks/Core/interface/fwLog.h"
0026 
0027 //
0028 // constants, enums and typedefs
0029 //
0030 
0031 //
0032 // static data member definitions
0033 //
0034 
0035 //
0036 // constructors and destructor
0037 //
0038 FWItemAccessorFactory::FWItemAccessorFactory() {}
0039 
0040 // FWItemAccessorFactory::FWItemAccessorFactory(const FWItemAccessorFactory& rhs)
0041 // {
0042 //    // do actual copying here;
0043 // }
0044 
0045 FWItemAccessorFactory::~FWItemAccessorFactory() {}
0046 
0047 //
0048 // assignment operators
0049 //
0050 // const FWItemAccessorFactory& FWItemAccessorFactory::operator=(const FWItemAccessorFactory& rhs)
0051 // {
0052 //   //An exception safe implementation is
0053 //   FWItemAccessorFactory temp(rhs);
0054 //   swap(rhs);
0055 //
0056 //   return *this;
0057 // }
0058 
0059 //
0060 // member functions
0061 //
0062 
0063 //
0064 // const member functions
0065 //
0066 
0067 /** Create an accessor for a given type @a iClass.
0068    
0069     @a iClass the type for which we need an accessor.
0070 
0071     If the type is known to ROOT to be some sort of collection,
0072     we return the a FWItemTVirtualCollectionProxyAccessor 
0073     constructed using the associated TVirtualCollectionProxy.
0074   
0075     If above is not true, we lookup the plugin based
0076     FWItemAccessorRegistry for a plugin that can handle the
0077     given type.
0078 
0079     If the type is not a collection but it contains only
0080     one element which is a collection, we return a 
0081     FWItemTVirtualCollectionProxyAccessor using the 
0082     TVirtualCollectionProxy of that element.
0083 
0084     Failing that, we return a FWItemSingleAccessor which threats
0085     the object as if it was not a collection. Notice that this also will
0086     mean that the product associated to @a iClass will not show up in the
0087     "Add Collection" table.
0088  */
0089 std::shared_ptr<FWItemAccessorBase> FWItemAccessorFactory::accessorFor(const TClass *iClass) const {
0090   static const bool debug = false;
0091 
0092   TClass *member = nullptr;
0093   size_t offset = 0;
0094 
0095   if (hasTVirtualCollectionProxy(iClass)) {
0096     if (debug)
0097       fwLog(fwlog::kDebug) << "class " << iClass->GetName() << " uses FWItemTVirtualCollectionProxyAccessor."
0098                            << std::endl;
0099     return std::make_shared<FWItemTVirtualCollectionProxyAccessor>(
0100         iClass, std::shared_ptr<TVirtualCollectionProxy>(iClass->GetCollectionProxy()->Generate()));
0101   }
0102 
0103   // Iterate on the available plugins and use the one which handles
0104   // the iClass type.
0105   // NOTE: This is done only a few times, not really performance critical.
0106   // If you want this to be fast, the loop can be moved in the
0107   // constructor. Notice that this will require constructing FWEventItemsManager
0108   // after the plugin manager (i.e. invoking FWLiteEnabler::enable()) is configured
0109   // (i.e. invoking FWLiteEnabler::enable()) in CmsShowMain.
0110   std::string accessorName;
0111   if (hasAccessor(iClass, accessorName)) {
0112     if (debug)
0113       fwLog(fwlog::kDebug) << "class " << iClass->GetName() << " uses " << accessorName << "." << std::endl;
0114     return std::shared_ptr<FWItemAccessorBase>(FWItemAccessorRegistry::get()->create(accessorName, iClass));
0115   }
0116 
0117   if (hasMemberTVirtualCollectionProxy(iClass, member, offset)) {
0118     if (debug)
0119       fwLog(fwlog::kDebug) << "class " << iClass->GetName() << " only contains data member " << member->GetName()
0120                            << " which uses FWItemTVirtualCollectionProxyAccessor." << std::endl;
0121 
0122     return std::make_shared<FWItemTVirtualCollectionProxyAccessor>(
0123         iClass, std::shared_ptr<TVirtualCollectionProxy>(member->GetCollectionProxy()->Generate()), offset);
0124   }
0125 
0126   return std::make_shared<FWItemSingleAccessor>(iClass);
0127 }
0128 
0129 /** Helper method which @return true if the passes @a iClass can be accessed via
0130     TVirtualCollectionProxy.
0131   */
0132 bool FWItemAccessorFactory::hasTVirtualCollectionProxy(const TClass *iClass) {
0133   // Check if this is a collection known by ROOT but also that the item held by
0134   // the colletion actually has a dictionary
0135   return iClass && iClass->GetCollectionProxy() && iClass->GetCollectionProxy()->GetValueClass() &&
0136          iClass->GetCollectionProxy()->GetValueClass()->IsLoaded();
0137 }
0138 
0139 /** Helper method which checks if the object has only one data member and 
0140     if that data memeber can be accessed via a TVirtualCollectionProxy.
0141     
0142     @a oMember a reference to the pointer which will hold the actual TClass
0143      of the datamember to be used to build the TVirtualCollectionProxy.
0144  
0145     @oOffset a reference which will hold the offset of the member relative
0146      to the beginning address of a class instance.
0147     
0148     @return true if this is the case, false otherwise.
0149 */
0150 bool FWItemAccessorFactory::hasMemberTVirtualCollectionProxy(const TClass *iClass, TClass *&oMember, size_t &oOffset) {
0151   assert(iClass->GetTypeInfo());
0152   edm::TypeWithDict dataType(*(iClass->GetTypeInfo()));
0153   assert(bool(dataType));
0154 
0155   // If the object has more than one data member, we avoid guessing.
0156   edm::TypeDataMembers members(dataType);
0157   if (members.size() != 1)
0158     return false;
0159 
0160   edm::MemberWithDict member(*members.begin());
0161   edm::TypeWithDict memType(member.typeOf());
0162 
0163   if (bool(memType) == false) {
0164     fwLog(fwlog::kDebug) << "FWItemAccessorFactory::hasMemberTVirtualCollectionProxy memtype not exhisiting "
0165                          << iClass->GetName() << "\n";
0166     return false;
0167   }
0168   if (memType.invalidTypeInfo()) {
0169     fwLog(fwlog::kDebug) << "FWItemAccessorFactory::hasMemberTVirtualCollectionProxy class " << iClass->GetName()
0170                          << " has invalid member type." << std::endl
0171                          << memType << "\n";
0172     return false;
0173   }
0174 
0175   oMember = TClass::GetClass(memType.typeInfo());
0176   oOffset = member.offset();
0177 
0178   // Check if this is a collection known by ROOT but also that the item held by
0179   // the colletion actually has a dictionary
0180 
0181   if (!hasTVirtualCollectionProxy(oMember))
0182     return false;
0183 
0184   return true;
0185 }
0186 
0187 /** Helper method which can be used to retrieve the name of the accessor 
0188     plugin which has to be created for a object of type @a iClass.
0189     
0190     The result is stored in the passed reference @a result.
0191     
0192     @return true if the plugin coul be found, false otherwise.
0193  */
0194 bool FWItemAccessorFactory::hasAccessor(const TClass *iClass, std::string &result) {
0195   const std::vector<edmplugin::PluginInfo> &available =
0196       edmplugin::PluginManager::get()->categoryToInfos().find("cmsShow FWItemAccessorBase")->second;
0197 
0198   for (size_t i = 0, e = available.size(); i != e; ++i) {
0199     std::string name = available[i].name_;
0200     std::string type = name.substr(0, name.find_first_of('@'));
0201     if (iClass->GetTypeInfo()->name() == type) {
0202       result.swap(name);
0203       return true;
0204     }
0205   }
0206   return false;
0207 }
0208 
0209 /** Helper method which checks if the object will be treated as a collection.
0210  
0211  @return true if this is the case, false otherwise.
0212  */
0213 
0214 bool FWItemAccessorFactory::classAccessedAsCollection(const TClass *iClass) {
0215   std::string accessorName;
0216   TClass *member = nullptr;
0217   size_t offset = 0;
0218 
0219   // This is pretty much the same thing that happens
0220   return (FWItemAccessorFactory::hasTVirtualCollectionProxy(iClass) ||
0221           FWItemAccessorFactory::hasMemberTVirtualCollectionProxy(iClass, member, offset) ||
0222           FWItemAccessorFactory::hasAccessor(iClass, accessorName));
0223 }
0224 
0225 //
0226 // static member functions
0227 //