Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:39

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once
0006 
0007 #include <string>
0008 #include <sstream>
0009 #include <set>
0010 #include <vector>
0011 #include <cassert>
0012 #include <typeinfo>
0013 
0014 #include <JANA/Utils/JTypeInfo.h>
0015 #include <JANA/JLogger.h>
0016 #include <JANA/JException.h>
0017 
0018 /// The JObject class is a base class for all data classes.
0019 /// (See JFactory for algorithm classes.)
0020 
0021 /// The JOBJECT_PUBLIC macro is used to generate the correct className() overrides for a JObject subclass
0022 #define JOBJECT_PUBLIC(T) \
0023     static const std::string static_className() {return #T;} \
0024     const std::string className() const override {return #T;} \
0025 
0026 
0027 struct JObjectMember {
0028     /// A plain-old data structure for describing one member of a JObject
0029     std::string name;        // E.g. "E_tot"
0030     std::string type;        // E.g. "float"
0031     std::string value;       // E.g. "22.2e-2"
0032     std::string description; // E.g. "GeV"
0033 };
0034 
0035 class JObjectSummary {
0036     /// A container data structure for collecting information about JObjects. This is meant to be
0037     /// used by tools for debugging/visualizing/introspecting. The information for each member is
0038     /// collected by JObject::Summarize().
0039 
0040     std::vector<JObjectMember> m_fields;
0041 
0042 public:
0043     /// get_fields() returns a copy of all JObjectMember information collected so far.
0044     std::vector<JObjectMember> get_fields() const {
0045         return m_fields;
0046     }
0047 
0048     /// add() is used to insert a new row of JObjectMember data
0049     template <typename T>
0050     void add(const T& x, const char* name, const char* format, const char* description="") {
0051 
0052         char buffer[256];
0053         snprintf(buffer, 256, format, x);
0054         m_fields.push_back({name, JTypeInfo::builtin_typename<T>(), buffer, description});
0055     }
0056 
0057     /// add() is used to insert a new row of JObjectMember data
0058     void add(const JObjectMember &objectMember){
0059         m_fields.push_back(objectMember);
0060     }
0061 };
0062 
0063 class JObject{
0064     public:
0065         JObject() = default;
0066         virtual ~JObject() = default;
0067 
0068         virtual const std::string className() const {
0069             /// className returns a string representation of the name of this class.
0070             /// This won't automatically do the right thing -- in each JObject subclass,
0071             /// the user either needs to use the JOBJECT_PUBLIC macro,
0072             /// or override this method while keeping the same method body.
0073             return JTypeInfo::demangle<decltype(*this)>();
0074         }
0075 
0076         // Associated objects
0077         inline void AddAssociatedObject(const JObject *obj);
0078         inline void AddAssociatedObjectAutoDelete(JObject *obj, bool auto_delete=true);
0079         inline void RemoveAssociatedObject(const JObject *obj);
0080         inline void ClearAssociatedObjects(void);
0081         inline bool IsAssociated(const JObject* locObject) const {return (associated.find(locObject) != associated.end());}
0082 
0083         template<class T> const T* GetSingle() const;
0084         template<class T> std::vector<const T*> Get() const;
0085 
0086         // JANA1 compatibility getters
0087         template<typename T>
0088         void GetSingle(const T* &ptrs, std::string classname="") const;
0089 
0090         template<typename T>
0091         void GetT(std::vector<const T*> &ptrs) const;
0092 
0093         template<typename T>
0094         void Get(std::vector<const T*> &ptrs, std::string classname="", int max_depth=1000000) const;
0095 
0096         template<typename T>
0097         void GetAssociatedAncestors(std::set<const JObject*> &already_checked,
0098                                     int &max_depth,
0099                                     std::set<const T*> &objs_found,
0100                                     std::string classname="") const;
0101 
0102 
0103 
0104         // Convert to strings with pretty formatting for printing
0105         virtual void Summarize(JObjectSummary& summary) const;
0106 
0107     protected:
0108         std::set<const JObject*> associated;
0109         std::set<JObject*> auto_delete;
0110 };
0111 
0112 
0113 //--------------------------
0114 // AddAssociatedObject
0115 //--------------------------
0116 void JObject::AddAssociatedObject(const JObject *obj)
0117 {
0118     /// Add a JObject to the list of associated objects
0119     assert(obj!=NULL);
0120     associated.insert(obj);
0121 }
0122 
0123 //--------------------------
0124 // AddAssociatedObjectAutoDelete
0125 //--------------------------
0126 void JObject::AddAssociatedObjectAutoDelete(JObject *obj, bool auto_delete)
0127 {
0128     /// Add a JObject to the list of associated objects. If the auto_delete
0129     /// flag is true, then automatically delete it when this object is
0130     /// deleted. Otherwise, this behaves identically to the AddAssociatedObject
0131     /// method.
0132     ///
0133     /// Note that if the object is removed via RemoveAssociatedObject(...)
0134     /// then the object is NOT deleted. BUT, if the entire list of associated
0135     /// objects is cleared via ClearAssociatedObjects, then the object will
0136     /// be deleted.
0137 
0138     AddAssociatedObject(obj);
0139     if(auto_delete) this->auto_delete.insert(obj);
0140 }
0141 
0142 //--------------------------
0143 // RemoveAssociatedObject
0144 //--------------------------
0145 void JObject::RemoveAssociatedObject(const JObject *obj)
0146 {
0147     /// Remove the specified JObject from the list of associated
0148     /// objects. This will NOT delete the object even if the
0149     /// object was added with the AddAssociatedObjectAutoDelete(...)
0150     /// method with the auto_delete flag set.
0151 
0152     auto iter = associated.find(obj);
0153 
0154     if(iter!=associated.end()){
0155         associated.erase(iter);
0156     }
0157 }
0158 
0159 //--------------------------
0160 // ClearAssociatedObjects
0161 //--------------------------
0162 void JObject::ClearAssociatedObjects(void)
0163 {
0164     /// Remove all associated objects from the associated objects list.
0165     /// This will also delete any objects that were added via the
0166     /// AddAssociatedObjectAutoDelete(...) method with the auto_delete
0167     /// flag set.
0168 
0169     // Clear pointers to associated objects
0170     associated.clear();
0171 
0172     // Delete objects in the auto_delete list
0173     for( auto p : auto_delete ) delete p;
0174     auto_delete.clear();
0175 }
0176 
0177 
0178 template<class T>
0179 const T* JObject::GetSingle() const {
0180     /// This is a convenience method that can be used to get a pointer to the single associated object of type T.
0181     /// If no object is found, this will return nullptr.
0182     /// If multiple objects are found, this will throw a JException.
0183 
0184     const T* last_found = nullptr;
0185     for (auto obj : associated) {
0186         auto t = dynamic_cast<const T*>(obj);
0187         if (t != nullptr) {
0188             if (last_found == nullptr) {
0189                 last_found = t;
0190             }
0191             else {
0192                 throw JException("JObject::GetSingle(): Multiple objects found.");
0193             }
0194         }
0195     }
0196     if (last_found == nullptr) {
0197         // If nothing found, attempt matching by strings.
0198         // Why? Because dl and RTTI aren't playing nicely together;
0199         // each plugin might assign a different typeid to the same class.
0200         std::string classname = JTypeInfo::demangle<T>();
0201         for (auto obj : associated) {
0202             if (obj->className() == classname) {
0203                 if (last_found == nullptr) {
0204                     last_found = reinterpret_cast<const T*>(obj);
0205                 }
0206                 else {
0207                     throw JException("JObject::GetSingle(): Multiple objects found.");
0208                 }
0209             }
0210         }
0211     }
0212     return last_found;
0213 }
0214 
0215 template<typename T>
0216 std::vector<const T*> JObject::Get() const {
0217     /// Returns a vector of pointers to all associated objects of type T.
0218 
0219     std::vector<const T*> results;
0220     for (auto obj : associated) {
0221         const T* t = dynamic_cast<const T*>(obj);
0222         if (t != nullptr) {
0223             results.push_back(t);
0224         }
0225     }
0226     if (results.empty()) {
0227         // If nothing found, attempt matching by strings.
0228         // Why? Because dl and RTTI aren't playing nicely together;
0229         // each plugin might assign a different typeid to the same class.
0230 
0231         std::string classname = JTypeInfo::demangle<T>();
0232         for (auto obj : associated) {
0233             if (obj->className() == classname) {
0234                 results.push_back(reinterpret_cast<const T*>(obj));
0235             }
0236         }
0237     }
0238     return results;
0239 }
0240 
0241 inline void JObject::Summarize(JObjectSummary& summary) const
0242 {
0243     /// A virtual method which allows the user to display the contents of
0244     /// a JObject in a formatted, structured way. This is optional, but recommended.
0245 
0246     /// Fill in the JObjectSummary container with information for each
0247     /// member variable of the JObject using JObjectSummary::add(...).
0248     /// This accepts a reference to the variable itself, the variable name,
0249     /// a printf-style format string, and an optional description string which is
0250     /// good for communicating things like units.
0251 
0252     /// For convenience, we provide a NAME_OF macro, which will turn the member
0253     /// variable name into a string, rather than having the user write it out manually.
0254     /// This is useful if you use automatic refactoring tools, which otherwise
0255     /// might allow the variable name and the stringified name to get out of sync.
0256 
0257     summary.add((unsigned long) this, "JObject", "0x%08x");
0258 }
0259 
0260 
0261 /// The following have been added purely for compatibility with JANA1, in order to make
0262 /// porting halld_recon more tractable.
0263 
0264 template<class T>
0265 void JObject::GetSingle(const T* &t, std::string classname) const
0266 {
0267     /// This is a convenience method that can be used to get a pointer to the single
0268     /// associate object of type T.
0269     ///
0270     /// The objects are chosen by matching their class names
0271     /// (obtained via JObject::className()) either
0272     /// to the one provided in classname or to T::static_className()
0273     /// if classname is an empty string.
0274     ///
0275     /// If no object of the specified type is found, a NULL pointer is
0276     /// returned.
0277 
0278     t = NULL;
0279 
0280     if(classname=="")classname=T::static_className();
0281 
0282     //map<const JObject*, string>::const_iterator iter = associated.begin();
0283     //for(; iter!=associated.end(); iter++){
0284     for( auto obj : associated ){
0285         if( classname == obj->className() ){
0286             t = dynamic_cast<const T*>(obj);
0287             if(t!=NULL)return;
0288         }
0289     }
0290 }
0291 
0292 template<typename T>
0293 void JObject::GetT(std::vector<const T*> &ptrs) const
0294 {
0295     /// Fill the given vector with pointers to the associated
0296     /// JObjects of the type on which the vector is based. This is
0297     /// similar to the Get() method except objects are selected
0298     /// by attempting a dynamic_cast to type const T*. This allows
0299     /// one to select a list of all objects who have a type T
0300     /// somewhere in their inheritance chain.
0301     ///
0302     /// A potential issue with this method is that the dynamic_cast
0303     /// does not always work correctly for objects created via a
0304     /// plugin when the cast occurs outside of the plugin or
0305     /// vice versa.
0306     ///
0307     /// The contents of ptrs are cleared upon entry.
0308 
0309     ptrs.clear();
0310 
0311     //map<const JObject*, string>::const_iterator iter = associated.begin();
0312     //for(; iter!=associated.end(); iter++){
0313     for( auto obj : associated ){
0314         const T *ptr = dynamic_cast<const T*>(obj);
0315         if(ptr != NULL)ptrs.push_back(ptr);
0316     }
0317 }
0318 
0319 
0320 template<typename T>
0321 void JObject::Get(std::vector<const T*> &ptrs, std::string classname, int max_depth) const
0322 {
0323     /// Fill the given vector with pointers to the associated objects of the
0324     /// type on which the vector is based. The objects are chosen by matching
0325     /// their class names (obtained via JObject::className()) either to the
0326     /// one provided in classname or to T::static_className() if classname is
0327     /// an empty string. Associations will be searched to a level of max_depth
0328     /// to find all objects of the requested type. By default, max_depth is
0329     /// set to a very large number so that all associations are found. To
0330     /// limit the search to only objects directly associated with this one,
0331     /// set max_depth to either "0" or "1".
0332     ///
0333     /// The contents of ptrs are cleared upon entry.
0334 
0335     if(classname=="")classname=T::static_className();
0336 
0337     // Use the GetAssociatedAncestors method which may call itself
0338     // recursively to search all levels of association (at or
0339     // below this object. Objects for which this is an associated
0340     // object are not checked for).
0341     std::set<const JObject*> already_checked;
0342     std::set<const T*> objs_found;
0343     int my_max_depth = max_depth;
0344     GetAssociatedAncestors(already_checked, my_max_depth, objs_found, classname);
0345 
0346     // Copy results into caller's container
0347     ptrs.clear();
0348     ptrs.insert(ptrs.end(), objs_found.begin(), objs_found.end());
0349 //  set<const T*>::iterator it;
0350 //  for(it=objs_found.begin(); it!=objs_found.end(); it++){
0351 //      ptrs.push_back(*it);
0352 //  }
0353 }
0354 
0355 template<typename T>
0356 void JObject::GetAssociatedAncestors(std::set<const JObject*> &already_checked, int &max_depth, std::set<const T*> &objs_found, std::string classname) const
0357 {
0358     /// Get associated objects of the specified type (either "T" or classname).
0359     /// Check also for associated objects of any associated objects
0360     /// to a level of max_depth associations. This method calls itself
0361     /// recursively so care is taken to only check the associated objects
0362     /// of each object encountered only once.
0363     ///
0364     /// The "already_checked" parameter should be passed in as an empty container
0365     /// that is used to keep track of which objects had their direct associations
0366     /// checked. "max_depth" indicates the maximum level of associations to check
0367     /// (n.b. both "0" and "1" means only check direct associations.) This must
0368     /// be passed as a reference to an existing int since it is modified in order
0369     /// to keep track of the current depth in the recursive calls. Set max_depth
0370     /// to a very high number (like 1000000) to check all associations. The
0371     /// "objs_found" container will contain the actual associated objects found.
0372     /// The objects are chosen by matching their class names (obtained via
0373     /// JObject::className()) either to the one provided in "classname" or to
0374     /// T::static_className() if classname is an empty string.
0375 
0376     if(already_checked.find(this) == already_checked.end()) already_checked.insert(this);
0377 
0378     if(classname=="")classname=T::static_className();
0379     max_depth--;
0380 
0381     //map<const JObject*, string>::const_iterator iter = associated.begin();
0382     for( auto obj : associated ){
0383 
0384         // Add to list if appropriate
0385         if( classname == obj->className() ){
0386             objs_found.insert( dynamic_cast<const T*>(obj) );
0387         }
0388 
0389         // Check this object's associated objects if appropriate
0390         if(max_depth<=0) continue;
0391         if(already_checked.find(obj) != already_checked.end()) continue;
0392         already_checked.insert(obj);
0393         obj->GetAssociatedAncestors(already_checked, max_depth, objs_found, classname);
0394     }
0395 
0396     max_depth++;
0397 }
0398 
0399