00001
00002 #ifndef INCLUDED_InstanceTracker_h_
00003 #define INCLUDED_InstanceTracker_h_
00004
00005 #include "plistCollections.h"
00006 #include "FamilyFactory.h"
00007 #include <string>
00008
00009
00010
00011
00012
00013
00014
00015 template<class FamilyT, typename ClassNameT=std::string, class FactoryBaseT=Factory1Arg<FamilyT,std::string>, template<class U> class FactoryT=FactoryBaseT::template Factory>
00016 class InstanceTracker : public plist::Dictionary, protected FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT> {
00017 public:
00018
00019 typedef plist::Dictionary::iterator iterator;
00020
00021 typedef plist::Dictionary::const_iterator const_iterator;
00022
00023
00024 typedef FamilyT FamilyType;
00025
00026 typedef ClassNameT ClassNameType;
00027
00028 typedef FactoryBaseT FactoryBaseType;
00029
00030 template<class T> struct FactoryType : FactoryT<T> {};
00031
00032
00033 InstanceTracker() : plist::Dictionary(), FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>() {}
00034
00035 using FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::getTypeNames;
00036 using FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::getNumTypes;
00037 using FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerType;
00038 using FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerFactory;
00039
00040
00041 template<class T> bool registerInstance(const std::string& name, T& inst);
00042
00043 template<class T> bool registerInstance(const std::string& name, T* inst);
00044
00045
00046
00047 template<class T> bool registerInstance(const ClassNameT& type, const std::string& name, T& inst);
00048
00049
00050
00051 template<class T> bool registerInstance(const ClassNameT& type, const std::string& name, T* inst);
00052
00053
00054 FamilyT* create(const ClassNameType& type, const std::string& name);
00055
00056 FamilyT* getInstance(const std::string& name );
00057
00058
00059
00060 bool destroy(const std::string& name);
00061
00062 void loadXML(xmlNode* node);
00063
00064 protected:
00065
00066
00067
00068
00069 class InstanceEntry : public plist::Dictionary {
00070 public:
00071
00072 explicit InstanceEntry(FamilyT* inst) : plist::Dictionary(), alloc(inst), instance(*inst) {}
00073
00074 explicit InstanceEntry(FamilyT& inst) : plist::Dictionary(), alloc(NULL), instance(inst) {}
00075
00076 ~InstanceEntry() { delete alloc; }
00077
00078 FamilyT* const alloc;
00079 FamilyT& instance;
00080
00081 private:
00082 InstanceEntry(const InstanceEntry&);
00083 InstanceEntry& operator=(const InstanceEntry&);
00084 };
00085
00086 private:
00087 InstanceTracker(const InstanceTracker&);
00088 InstanceTracker& operator=(const InstanceTracker&);
00089 };
00090
00091 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00092 template<class T>
00093 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerInstance(const std::string& name, T& inst) {
00094 if(findEntry(name)!=end())
00095 return false;
00096 plist::Dictionary* dinst=dynamic_cast<plist::Dictionary*>(&inst);
00097 if(dinst!=NULL) {
00098 addEntry(name,*dinst);
00099 } else {
00100 dinst=new InstanceEntry(inst);
00101 addEntry(name,dinst);
00102 }
00103 return true;
00104 }
00105 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00106 template<class T>
00107 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerInstance(const std::string& name, T* inst) {
00108 if(findEntry(name)!=end())
00109 return false;
00110 plist::Dictionary* dinst=dynamic_cast<plist::Dictionary*>(inst);
00111 if(dinst==NULL)
00112 dinst=new InstanceEntry(inst);
00113 addEntry(name,dinst);
00114 return true;
00115 }
00116 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00117 template<class T>
00118 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerInstance(const ClassNameT& type, const std::string& name, T& inst) {
00119 if(findEntry(name)!=end())
00120 return false;
00121 plist::Dictionary* dinst=dynamic_cast<plist::Dictionary*>(&inst);
00122 if(dinst!=NULL) {
00123 if(type.size()>0)
00124 dinst->addEntry(".type",new plist::Primitive<ClassNameT>(type),"Stores the typename of the class so it can be re-instantiated on load.\n** Do not edit ** ");
00125 addEntry(name,*dinst);
00126 } else {
00127 dinst=new InstanceEntry(inst);
00128 if(type.size()>0)
00129 dinst->addEntry(".type",new plist::Primitive<ClassNameT>(type),"Stores the typename of the class so it can be re-instantiated on load.\n** Do not edit ** ");
00130 addEntry(name,dinst);
00131 }
00132 return true;
00133 }
00134 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00135 template<class T>
00136 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::registerInstance(const ClassNameT& type, const std::string& name, T* inst) {
00137 if(findEntry(name)!=end())
00138 return false;
00139 plist::Dictionary* dinst=dynamic_cast<plist::Dictionary*>(inst);
00140 if(dinst==NULL)
00141 dinst=new InstanceEntry(inst);
00142 if(type.size()>0)
00143 dinst->addEntry(".type",new plist::Primitive<ClassNameT>(type),"Stores the typename of the class so it can be re-instantiated on load.\n** Do not edit ** ");
00144 addEntry(name,dinst);
00145 return true;
00146 }
00147
00148 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00149 FamilyT* InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::create(const ClassNameT& type, const std::string& name) {
00150 if(findEntry(name)!=end())
00151 return NULL;
00152 FamilyT* inst=FamilyFactory<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::create(type,name);
00153 if(inst==NULL)
00154 return NULL;
00155 registerInstance(type,name,inst);
00156 return inst;
00157 }
00158
00159 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00160 FamilyT* InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::getInstance(const std::string& name) {
00161 const_iterator it=findEntry(name);
00162 if(it==end())
00163 return NULL;
00164 if(InstanceEntry* inst=dynamic_cast<InstanceEntry*>(it->second))
00165 return &inst->instance;
00166 return dynamic_cast<FamilyT*>(it->second);
00167 }
00168
00169 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00170 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::destroy(const std::string& name) {
00171 const_iterator it=findEntry(name);
00172 if(it==end())
00173 return false;
00174 removeEntry(name);
00175 return true;
00176 }
00177
00178 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00179 void InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::loadXML(xmlNode* node) {
00180
00181 plist::Dictionary d;
00182 d.loadXML(node);
00183 for(plist::Dictionary::const_iterator it=d.begin(); it!=d.end(); ++it) {
00184 if(plist::Dictionary* dd = dynamic_cast<plist::Dictionary*>(it->second)) {
00185 plist::Dictionary::const_iterator obit = dd->findEntry(".type");
00186 if(obit==dd->end()) {
00187 std::cerr << "ERROR: could not instantiate driver named '" << it->first << "'; no '.type' field found!" << std::endl;
00188 } else {
00189 std::string typestr = obit->second->toString();
00190 plist::Dictionary::const_iterator drobit = findEntry(it->first);
00191 plist::ObjectBase * drob = (drobit==end()) ? NULL : drobit->second;
00192 if(plist::Dictionary* dr = dynamic_cast<plist::Dictionary*>(drob)) {
00193 plist::Dictionary::const_iterator tyobit = dr->findEntry(".type");
00194 if(tyobit==dr->end())
00195 std::cerr << "WARNING: Driver dictionary lacking .type field for '" << it->first << "'" << std::endl;
00196 else if(tyobit->second->toString()==typestr)
00197 continue;
00198 destroy(it->first);
00199 dr=NULL;
00200 }
00201 if(create(typestr,it->first)==NULL)
00202 std::cerr << "ERROR: failed to instantiate driver named '" << it->first << "' with type '" << typestr << "'" << std::endl;
00203 }
00204 } else {
00205 std::cerr << "ERROR: could not instantiate driver named '" << it->first << "'; not a dictionary!" << std::endl;
00206 }
00207 }
00208
00209 plist::Dictionary::loadXML(node);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 #endif