Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-05 22:48:10

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   assert(bool(memType));
0163   oMember = TClass::GetClass(memType.typeInfo());
0164   oOffset = member.offset();
0165 
0166   // Check if this is a collection known by ROOT but also that the item held by
0167   // the colletion actually has a dictionary
0168 
0169   if (!hasTVirtualCollectionProxy(oMember))
0170     return false;
0171 
0172   return true;
0173 }
0174 
0175 /** Helper method which can be used to retrieve the name of the accessor 
0176     plugin which has to be created for a object of type @a iClass.
0177     
0178     The result is stored in the passed reference @a result.
0179     
0180     @return true if the plugin coul be found, false otherwise.
0181  */
0182 bool FWItemAccessorFactory::hasAccessor(const TClass *iClass, std::string &result) {
0183   const std::vector<edmplugin::PluginInfo> &available =
0184       edmplugin::PluginManager::get()->categoryToInfos().find("cmsShow FWItemAccessorBase")->second;
0185 
0186   for (size_t i = 0, e = available.size(); i != e; ++i) {
0187     std::string name = available[i].name_;
0188     std::string type = name.substr(0, name.find_first_of('@'));
0189     if (iClass->GetTypeInfo()->name() == type) {
0190       result.swap(name);
0191       return true;
0192     }
0193   }
0194   return false;
0195 }
0196 
0197 /** Helper method which checks if the object will be treated as a collection.
0198  
0199  @return true if this is the case, false otherwise.
0200  */
0201 
0202 bool FWItemAccessorFactory::classAccessedAsCollection(const TClass *iClass) {
0203   std::string accessorName;
0204   TClass *member = nullptr;
0205   size_t offset = 0;
0206 
0207   // This is pretty much the same thing that happens
0208   return (FWItemAccessorFactory::hasTVirtualCollectionProxy(iClass) ||
0209           FWItemAccessorFactory::hasMemberTVirtualCollectionProxy(iClass, member, offset) ||
0210           FWItemAccessorFactory::hasAccessor(iClass, accessorName));
0211 }
0212 
0213 //
0214 // static member functions
0215 //