JObject.h

Go to the documentation of this file.
00001 // $Id: JObject.h 1709 2006-04-26 20:34:03Z davidl $
00002 //
00003 //    File: JObject.h
00004 // Created: Wed Aug 17 10:57:09 EDT 2005
00005 // Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc)
00006 //
00007 
00008 #ifndef _JObject_
00009 #define _JObject_
00010 
00011 #include <sstream>
00012 #include <cassert>
00013 #include <map>
00014 #include <vector>
00015 #include <string>
00016 #include <typeinfo>
00017 using std::pair;
00018 using std::map;
00019 using std::vector;
00020 using std::string;
00021 using std::stringstream;
00022 
00023 // The following is here just so we can use ROOT's THtml class to generate documentation.
00024 #ifdef __CINT__
00025 #include "cint.h"
00026 #endif
00027 
00028 
00029 /// The JObject class is a base class for all data classes.
00030 /// (See JFactory and JFactory_base for algorithm classes.)
00031 ///
00032 ///
00033 /// The following line should be included in the public definition of all
00034 /// classes which inherit from JObject with the argument being the name of the
00035 /// class without any quotes.
00036 /// e.g. for a class named "MyClass" :
00037 /// 
00038 ///  public:
00039 ///     JOBJECT_PUBLIC(MyClass);
00040 ///
00041 /// This will define a virtual method <i>className()</i> and a static
00042 /// method <i>static_className()</i> that are used by JANA to identify
00043 /// the object's last generation in the inheritance chain by name. This
00044 /// also allows for possible upgrades to JANA in the future without
00045 /// requiring classes that inherit from JObject to be redefined explicity.
00046 #define JOBJECT_PUBLIC(T) \
00047    virtual const char* className(void) const {return static_className();} \
00048    static const char* static_className(void) {return #T;}
00049 
00050 // Place everything in JANA namespace
00051 namespace jana{
00052 
00053 class JObject{
00054 
00055    public:
00056       JOBJECT_PUBLIC(JObject);
00057 
00058       typedef unsigned long oid_t;
00059    
00060       JObject(){id = (oid_t)this; append_types=false;}
00061       JObject( oid_t aId ) : id( aId ) { append_types=false;}
00062 
00063       virtual ~JObject(){}
00064       
00065       /// Test if this object is of type T by checking its className() against T::static_className()
00066       template<typename T> bool IsA(const T *t) const {return dynamic_cast<const T*>(this)!=0L;}
00067 
00068       /// Test if this object is of type T (or a descendant) by attempting a dynamic cast
00069       template<typename T> bool IsAT(const T *t) const {return dynamic_cast<const T*>(this)!=0L;}
00070 
00071       // Methods for handling associated objects
00072       inline void AddAssociatedObject(const JObject *obj);
00073       inline void RemoveAssociatedObject(const JObject *obj);
00074       template<typename T> void Get(vector<const T*> &ptrs, string classname="") const ;
00075       template<typename T> void GetT(vector<const T*> &ptrs) const ;
00076 
00077       // Methods for handling pretty formatting for dumping to the screen or file
00078       virtual void toStrings(vector<pair<string,string> > &items)const;
00079       template<typename T> void AddString(vector<pair<string,string> > &items, const char *name, const char *format, const T &val) const;
00080 
00081       bool GetAppendTypes(void) const {return append_types;} ///< Get state of append_types flag (for AddString)
00082       void SetAppendTypes(bool append_types){this->append_types=append_types;} ///< Set state of append_types flag (for AddString)
00083 
00084       oid_t id;
00085    
00086    private:
00087       
00088       bool append_types;
00089       map<const JObject*, string> associated;
00090       
00091 };
00092 
00093 #ifndef __CINT__
00094 
00095 //--------------------------
00096 // AddAssociatedObject
00097 //--------------------------
00098 void JObject::AddAssociatedObject(const JObject *obj)
00099 {
00100    /// Add a JObject to the list of associated objects
00101 
00102    assert(obj!=NULL);
00103    
00104    associated[obj] = obj->className();
00105 }
00106 
00107 //--------------------------
00108 // RemoveAssociatedObject
00109 //--------------------------
00110 void JObject::RemoveAssociatedObject(const JObject *obj)
00111 {
00112    /// Remove the specified JObject from the list of associated
00113    /// objects.
00114 
00115    map<const JObject*, string>::iterator iter = associated.find(obj);
00116    
00117    if(iter!=associated.end()){
00118       associated.erase(iter);
00119    }
00120 }
00121 
00122 //--------------------------
00123 // Get
00124 //--------------------------
00125 template<typename T>
00126 void JObject::Get(vector<const T*> &ptrs, string classname) const
00127 {
00128    /// Fill the given vector with pointers to the associated 
00129    /// JObjects of the type on which the vector is based. The
00130    /// objects are chosen by matching their class names 
00131    /// (obtained via JObject::className()) either
00132    /// to the one provided in classname or to T::static_className()
00133    /// if classname is an empty string.
00134    ///
00135    /// The contents of ptrs are cleared upon entry.
00136    
00137    ptrs.clear();
00138    
00139    if(classname=="")classname=T::static_className();
00140    
00141    map<const JObject*, string>::const_iterator iter = associated.begin();
00142    for(; iter!=associated.end(); iter++){
00143       if(iter->second == classname){
00144          const T *ptr = dynamic_cast<const T*>(iter->first);
00145          ptrs.push_back(ptr);
00146       }
00147    }  
00148 }
00149 
00150 //--------------------------
00151 // GetT
00152 //--------------------------
00153 template<typename T>
00154 void JObject::GetT(vector<const T*> &ptrs) const
00155 {
00156    /// Fill the given vector with pointers to the associated 
00157    /// JObjects of the type on which the vector is based. This is
00158    /// similar to the Get() method except objects are selected
00159    /// by attempting a dynamic_cast to type const T*. This allows
00160    /// one to select a list of all objects who have a type T
00161    /// somewhere in their inheritance chain.
00162    ///
00163    /// A potential issue with this method is that the dynamic_cast
00164    /// does not always work correctly for objects created via a
00165    /// plugin when the cast occurs outside of the plugin or
00166    /// vice versa.
00167    ///
00168    /// The contents of ptrs are cleared upon entry.
00169    
00170    ptrs.clear();
00171    
00172    string classname=T::static_className();
00173    
00174    map<const JObject*, string>::const_iterator iter = associated.begin();
00175    for(; iter!=associated.end(); iter++){
00176       const T *ptr = dynamic_cast<const T*>(iter->first);
00177       if(ptr != NULL)ptrs.push_back(ptr);
00178    }  
00179 }
00180 
00181 //--------------------------
00182 // toStrings
00183 //--------------------------
00184 inline void JObject::toStrings(vector<pair<string,string> > &items) const
00185 {
00186    /// Fill the given "items" vector with items representing the (important)
00187    /// data members of this object. The structure of "items" is a vector
00188    /// of pairs. The "first" element of the pair is the name of the item
00189    /// as it should be displayed when dumping the item to the screen. For
00190    /// example, one may wish to include units using a string like "r (cm)".
00191    /// The "second" element of the pair is a formatted string containing the
00192    /// value as it should be displayed.
00193    ///
00194    /// To facilitate this, the AddString() method exists which allows
00195    /// items to be added with the desired formatting using a single line.
00196    ///
00197    /// This is a virtual method that is expected (but not required)
00198    /// to be implemented by all classes that inherit from JObject.
00199 
00200    AddString(items, "JObject", "0x%08x", (unsigned long)this);
00201 }
00202 
00203 //--------------------------
00204 // AddString
00205 //--------------------------
00206 template<typename T>
00207 void JObject::AddString(vector<pair<string,string> > &items, const char *name, const char *format, const T &val) const
00208 {
00209    /// Write the given value (val) to a string using the sprintf style formatting
00210    /// string (format) and add it to the given vector (items) with the column
00211    /// name "name". This is intended for use in the toStrings() method of
00212    /// classes that inherit from JObject.
00213    ///
00214    /// The append_type flag provides a facility for recording the data type
00215    /// and value with default formatting into items. This can be used 
00216    /// by a generic convertor (not part of JANA) to auto-generate a
00217    /// representation of this object for use in some other persistence
00218    /// package (e.g. ROOT files).
00219    ///
00220    /// If the append_types flag is set then the data type of "val" is
00221    /// automatically appended with a colon (:) separator to the
00222    /// name (first) part of the pair. In addition, "val" is converted
00223    /// using stringstream and appended as well, also with a colon (:)
00224    /// separator. For example, if the value of name passed in is "px"
00225    /// and T is of type double, then the first member of the pair
00226    /// appended to items will be something like "px:double:1.23784"
00227    /// which can be decifered later to get the name, type, and value
00228    /// of the data member.
00229    ///
00230    /// By default, the append_types flag is not set and the name part
00231    /// of the pair is a straight copy of the name argument that is
00232    /// passed in.
00233 
00234    char str[256];
00235    sprintf(str, format, val);
00236 
00237    stringstream ss;
00238    ss<<name;
00239    if(append_types){
00240       if(typeid(T)==typeid(int)){
00241          ss<<":int:"<<val;
00242       }else if(typeid(T)==typeid(unsigned int)){
00243          ss<<":uint:"<<val;
00244       }else if(typeid(T)==typeid(long)){
00245          ss<<":long:"<<val;
00246       }else if(typeid(T)==typeid(unsigned long)){
00247          ss<<":ulong:"<<val;
00248       }else if(typeid(T)==typeid(float)){
00249          ss<<":float:"<<val;
00250       }else if(typeid(T)==typeid(double)){
00251          ss<<":double:"<<val;
00252       }else if(typeid(T)==typeid(string)){
00253          ss<<":string:"<<val;
00254       }else if(typeid(T)==typeid(const char*)){
00255          ss<<":string:"<<val;
00256       }else if(typeid(T)==typeid(char*)){
00257          ss<<":string:"<<val;
00258       }else{
00259          ss<<":unknown:"<<str;
00260       }
00261    }
00262 
00263    pair<string, string> item;
00264    item.first = ss.str();
00265    item.second = string(str);
00266    items.push_back(item);
00267 }
00268 
00269 #endif // __CINT__
00270 
00271 
00272 } // Close JANA namespace
00273 
00274 #endif // _JObject_
00275 

Generated on Wed Jun 10 22:31:31 2009 for JANA (JLab ANAlysis) by  doxygen 1.5.1