JANA
JFactory.h
Go to the documentation of this file.
00001 // $Id: JFactory.h 1733 2006-05-02 17:17:32Z davidl $
00002 
00003 
00004 #ifndef _JFACTORY_H_
00005 #define _JFACTORY_H_
00006 
00007 
00008 
00009 #include "JObject.h"
00010 
00011 
00012 #include <vector>
00013 #include <string>
00014 using std::vector;
00015 using std::string;
00016 
00017 #include "JEventLoop.h"
00018 #include "JFactory_base.h"
00019 #include "JEvent.h"
00020 
00021 // The following is here just so we can use ROOT's THtml class to generate documentation.
00022 #ifdef __CINT__
00023 class pthread_mutex_t;
00024 typedef unsigned long pthread_t;
00025 typedef unsigned long oid_t;
00026 #endif
00027 
00028 // Place everything in JANA namespace
00029 namespace jana{
00030 
00031 ///
00032 /// JANA Data Factory (base class for algorithms)
00033 ///
00034 /// All data (except that read from the data source) must
00035 /// be derived from the data that was read from the source.
00036 /// One JFactory object should exist for each type of data
00037 /// that is "generated". For example: Clusters in a calorimeter
00038 /// are generated from individual "Hits" in the calorimeter.
00039 /// 
00040 /// JFactory is the templated base class which all factories
00041 /// are derived from.
00042 ///
00043 /// At the user level, factory classes will be defined
00044 /// which inherit from this templated base class. By
00045 /// inheriting from a template, the derived factory class
00046 /// will automatically have a high degree of type safety
00047 /// since the "_data" vector will be specific to the type
00048 /// of objects the factory produces. This class (JFactory)
00049 /// inherits from JFactory_base so that all factories can
00050 /// be treated equally (polymorphism) by the JEventLoop object.
00051 ///
00052 /// Instantiating a JFactory<T> object itself would be pointless
00053 /// since they would use the default  init(), brun(),evnt(),erun(),
00054 /// and fini()
00055 /// methods from JEventProcessor which do nothing. Instead,
00056 /// A new class should be derived from this one which implements
00057 /// its own init(), brun(),evnt(),erun(), and fini() methods.
00058 
00059 //-----------------------
00060 // class JFactory
00061 //-----------------------
00062 template<class T>
00063 class JFactory:public JFactory_base{
00064    
00065    public:
00066       JFactory(const char *tag="");
00067       ~JFactory();
00068 
00069       enum data_origin_t{
00070          ORIGIN_NONE,
00071          ORIGIN_FACTORY,
00072          ORIGIN_EXTERNAL
00073       };
00074       
00075       vector<void*>& Get(void);
00076       jerror_t Get(vector<const T*> &d);
00077       int GetNrows(void);
00078       data_origin_t GetDataOrigin(void){return data_origin;}
00079       inline const char* className(void){return T::static_className();}
00080       inline const char* GetDataClassName(void){return className();}
00081       inline void toStrings(vector<vector<pair<string,string> > > &items, bool append_types=false) const;
00082       virtual const char* Tag(void){return tag_str;}
00083       inline int GetDataClassSize(void){return sizeof(T);}
00084       inline int GetEventCalled(void){return evnt_called;}
00085       inline int GetCheckSourceFirst(void){return !use_factory;}
00086       jerror_t CopyFrom(vector<const T*> &data);
00087       jerror_t CopyTo(vector<T*> &data);
00088       const T* GetByIDT(JObject::oid_t id);
00089       const JObject* GetByID(JObject::oid_t id){return dynamic_cast<const JObject*>(GetByIDT(id));}
00090       
00091 
00092    protected:
00093       vector<T*> _data;
00094       vector<void*>_vdata;
00095       int use_factory;
00096       const char* tag_str;
00097       
00098       jerror_t Reset(void);
00099       jerror_t HardReset(void);
00100       
00101       data_origin_t data_origin;
00102 };
00103 
00104 
00105 // The following is here just so we can use ROOT's THtml class to generate documentation.
00106 #ifndef __CINT__
00107 
00108 //-------------
00109 // JFactory
00110 //-------------
00111 template<class T>
00112 JFactory<T>::JFactory(const char *tag)
00113 {
00114    /// This is a base class that specific factories inherit from.
00115    /// my_devent will be kept and used to allow this factory to
00116    /// access other factories.
00117 
00118    // make sure vector is empty
00119    _data.clear(); // probably unnecessary
00120    
00121    // clear flags
00122    flags = WRITE_TO_OUTPUT;
00123    use_factory = 0;
00124    busy = 0;
00125    tag_str = tag;
00126    Ncalls_to_Get = 0;
00127    Ncalls_to_evnt = 0;
00128 
00129    // Allow any factory to have its debug_level set via environment variable
00130    debug_level = 0;
00131    string envar = string() + "DEBUG_" + GetDataClassName();
00132    char *ptr = getenv(envar.c_str());
00133    if(ptr)debug_level = atoi(ptr);
00134 }
00135 
00136 //-------------
00137 // ~JFactory
00138 //-------------
00139 template<class T>
00140 JFactory<T>::~JFactory()
00141 {
00142    /// Delete all objects in _data container.
00143    HardReset();
00144 }
00145 
00146 //-------------
00147 // Get
00148 //-------------
00149 template<class T>
00150 vector<void*>& JFactory<T>::Get(void)
00151 {
00152    /// Return a STL vector of pointers to the objects produced by the
00153    /// factory. The pointers are type cast as void* so this can be
00154    /// accessed through the JFactory_base base class. This just
00155    /// dispatches to the type specific Get(vector<const T*> &)
00156    /// method.
00157    vector<const T*> d;
00158    Get(d);
00159    
00160    // Copy the pointers into a vector of void*s.
00161    _vdata.clear();
00162    for(unsigned int i=0;i<_data.size();i++)_vdata.push_back((void*)_data[i]);
00163    
00164    return _vdata;
00165 }
00166 
00167 //-------------
00168 // Get
00169 //-------------
00170 template<class T>
00171 jerror_t JFactory<T>::Get(vector<const T*> &d)
00172 {
00173    /// Copy pointers to the objects produced by the factory into
00174    /// the vector reference passed. 
00175    /// Note that this method is accessed primarily from two places:
00176    /// This main one is JEventLoop::GetFromFactory which is called
00177    /// from JEventLoop::Get , the primary access method for factories
00178    /// and event processors.
00179    /// The second is through the JFactory<T>::Get() which is called
00180    /// through the JFactory_base::Get virtual method.
00181    /// That is used mainly by things that need to loop over all
00182    /// objects of all factories.
00183    ///
00184    /// This method will check first to make sure this factory hasn't
00185    /// already been called for this event.
00186    ///
00187    /// This also uses a busy flag to ensure we're not called
00188    /// recursively. i.e. we call a factory who calls another
00189    /// factory who eventually calls us. An exception is thrown
00190    /// (type jerror_t) with a value INFINITE_RECURSION if that
00191    /// situation is detected.
00192    
00193    
00194    // If evnt_called is set, then just copy the pointers and return
00195    if(evnt_called)return CopyFrom(d);
00196    
00197    // Check for infinite recursion through factory dependancies
00198    if(busy)throw(INFINITE_RECURSION);
00199    busy++;
00200    if(busy!=1)throw(INFINITE_RECURSION);  // Should we use a mutex here?
00201    
00202    // Grab the current event and run numbers
00203    int event_number = eventLoop->GetJEvent().GetEventNumber();
00204    int run_number = eventLoop->GetJEvent().GetRunNumber();
00205    
00206    // Make sure we're initialized
00207    if(!init_called){
00208       init();
00209       init_called = 1;
00210    }
00211    
00212    // Call brun routine if run number has changed or it's not been called
00213    if(run_number!=brun_runnumber){
00214       if(brun_called && !erun_called){
00215          erun();
00216          erun_called = 1;
00217       }
00218       brun_called = 0;
00219    }
00220    if(!brun_called){
00221       brun(eventLoop, run_number);
00222       brun_called = 1;
00223       erun_called = 0;
00224       brun_runnumber = run_number;
00225    }
00226    
00227    // Call evnt routine to generate data
00228    try{
00229       Ncalls_to_evnt++;
00230       evnt(eventLoop, event_number);
00231       CopyFrom(d);
00232    }catch(JException *exception){
00233       JEventLoop::error_call_stack_t cs;
00234       cs.factory_name = GetDataClassName();
00235       cs.tag = Tag();
00236       cs.filename = __FILE__;
00237       cs.line = __LINE__;
00238       eventLoop->AddToErrorCallStack(cs);
00239       throw exception;
00240    }
00241    evnt_called = 1;
00242    busy=0;
00243    
00244    return NOERROR;
00245 }
00246 
00247 //-------------
00248 // GetNrows
00249 //-------------
00250 template<class T>
00251 int JFactory<T>::GetNrows(void)
00252 {
00253    /// Return the number of objects for this factory for the
00254    /// current event. If the objects have not yet been created
00255    /// for the event, this will cause them to be generated 
00256    /// (or retreived from the source).
00257    if(!evnt_called){
00258       // In order to get the objects from the source, the Get() method
00259       // of the JEventLoop object must be called. This may seem
00260       // convoluted, but it's neccessary for things like janadump
00261       // that only have a list of JFactory_base pointers and
00262       // are not able to call the templated JEventLoop::Get()
00263       // method directly.
00264       // Note that we must use the Tag() method so it will pass
00265       // the tag from the subclass (if any). The tag_str member
00266       // is only in JFactory for when sources must auto-instantiate
00267       // a JFactory<> class.
00268       vector<const T*> d; // dummy placeholder
00269       eventLoop->Get(d,Tag());
00270    }
00271    
00272    return _data.size();
00273 }
00274 
00275 //-------------
00276 // Reset
00277 //-------------
00278 template<class T>
00279 jerror_t JFactory<T>::Reset(void)
00280 {
00281    /// Clear out the factories current contents unless the
00282    /// PERSISTANT flag is set.
00283    if(flags & (unsigned int)PERSISTANT)return NOERROR;
00284 
00285    // don't reset the evnt_called flag for persistent data because this
00286    // will force evnt to be called next event therby regenerating
00287    // the data
00288    
00289    return HardReset();
00290 }
00291 
00292 //-------------
00293 // HardReset
00294 //-------------
00295 template<class T>
00296 jerror_t JFactory<T>::HardReset(void)
00297 {
00298    
00299    /// Clear out the factories current contents.
00300    if(!TestFactoryFlag(NOT_OBJECT_OWNER)){
00301       for(unsigned int i=0;i<_data.size();i++){
00302          delete _data[i];
00303       }
00304    }
00305    _data.clear();
00306 
00307    evnt_called = 0;
00308    
00309    return NOERROR;
00310 }
00311 
00312 //-------------
00313 // CopyTo
00314 //-------------
00315 template<class T>
00316 jerror_t JFactory<T>::CopyTo(vector<T*> &data)
00317 {
00318    /// Copy object pointers into factory. Object ownership is
00319    /// transferred to the factory here so the caller should not
00320    /// delete the objects after calling this unless the factory's
00321    /// NOT_OBJECT OWNER flag is set (see
00322    /// SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER))
00323    /// This is how an external source such as a file can create
00324    /// the objects and put them in the factory. The objects will
00325    /// then be treated as though they were generated by the factory.
00326    /// i.e. they will be returned in subsequent calls to Get()
00327    /// and deleted at the start of the next event (sans 
00328    /// the NOT_OBJECT_OWNER or PERSISTANT flags).
00329 
00330    // Set flag so subsequent calls for this event will return this
00331    // data.
00332    evnt_called = 1;
00333       
00334    // Just copy into the _vdata vector since _data is not used outside
00335    // of the factory.
00336    _data.clear();
00337    for(unsigned int i=0;i<data.size();i++){
00338       _data.push_back(data[i]);
00339    }
00340 
00341    return NOERROR;
00342 }
00343 
00344 //-------------
00345 // CopyFrom
00346 //-------------
00347 template<class T>
00348 jerror_t JFactory<T>::CopyFrom(vector<const T*> &data)
00349 {
00350    /// Copy object pointers from private vector into "data"
00351    /// vector. This does not check if the evnt() routine
00352    /// was called, and it does not generate the data objects
00353    /// (use the Get(vector<const T*>) method for that).
00354    /// This only copies pointers to already existing objects.
00355    for(unsigned int i=0;i<_data.size(); i++)data.push_back(_data[i]);
00356    Ncalls_to_Get++;
00357    
00358    return NOERROR;
00359 }
00360 
00361 //-------------
00362 // GetByIDT
00363 //-------------
00364 template<class T>
00365 const T* JFactory<T>::GetByIDT(JObject::oid_t id)
00366 {
00367    for(unsigned int i=0;i<_data.size();i++)
00368       if(_data[i]->id == id)return (const T*)_data[i];
00369    return NULL;
00370 }
00371 
00372 //-------------
00373 // toStrings
00374 //-------------
00375 template<class T>
00376 void JFactory<T>::toStrings(vector<vector<pair<string,string> > > &items, bool append_types) const
00377 {
00378    /// Get the data for all objects already created by this factory for the
00379    /// given event by calling the toStrings() method of each one.
00380    ///
00381    /// Note that this will not activate the factory to generate the objects
00382    /// if they do not already exist.
00383    ///
00384    /// The value of <i>append_types</i> is used to set the append_types
00385    /// flag for each of the objects prior to calling its <i>toStrings</i>
00386    /// method. Afterwards, the value of the objects' append_types flag
00387    /// is reset to whatever value it had upon entry. Please see the documentation
00388    /// of the AddString method of JObject for more details on what this
00389    /// flag does.
00390    ///
00391    /// The items vector is cleared upon entry.
00392    
00393    items.clear();
00394    
00395    for(unsigned int i=0;i<_data.size();i++){
00396       vector<pair<string, string> > myitems;
00397       bool save_append_types = _data[i]->GetAppendTypes();
00398       _data[i]->SetAppendTypes(append_types);
00399       _data[i]->toStrings(myitems);
00400       _data[i]->SetAppendTypes(save_append_types);
00401       if(myitems.size()>0)items.push_back(myitems);
00402    }
00403 }
00404 
00405 #endif //__CINT__
00406 
00407 
00408 } // Close JANA namespace
00409 
00410 
00411 
00412 #endif // _JFACTORY_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines