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>() { setLoadSavePolicy(FIXED,SYNC); }
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(FamilyT* inst = dynamic_cast<FamilyT*>(it->second))
00165 return inst;
00166
00167 if(InstanceEntry* inst = dynamic_cast<InstanceEntry*>(it->second))
00168 return &inst->instance;
00169 if(it->second==NULL)
00170 std::cerr << "InstanceTracker had NULL entry for " << name << std::endl;
00171 else
00172 std::cerr << "InstanceTracker had entry of unknown type for " << name << std::endl;
00173 return NULL;
00174 }
00175
00176 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00177 bool InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::destroy(const std::string& name) {
00178 const_iterator it=findEntry(name);
00179 if(it==end())
00180 return false;
00181 removeEntry(name);
00182 return true;
00183 }
00184
00185
00186 struct InstanceTypeLoader : public virtual plist::Dictionary {
00187
00188 InstanceTypeLoader() : plist::Dictionary(), type() {
00189 addEntry(".type",type);
00190 setLoadSavePolicy(FIXED,SYNC);
00191 setUnusedWarning(false);
00192 }
00193
00194 plist::Primitive<std::string> type;
00195 };
00196
00197 template<class FamilyT, typename ClassNameT, class FactoryBaseT, template<class U> class FactoryT>
00198 void InstanceTracker<FamilyT,ClassNameT,FactoryBaseT,FactoryT>::loadXML(xmlNode* node) {
00199
00200 plist::DictionaryOf<InstanceTypeLoader> d;
00201 d.loadXML(node);
00202 for(plist::DictionaryOf<InstanceTypeLoader>::const_iterator it=d.begin(); it!=d.end(); ++it) {
00203 InstanceTypeLoader* dd = it->second;
00204 if(dd->type.size()==0) {
00205 std::cerr << "ERROR: could not instantiate driver named '" << it->first << "'; no '.type' field found!" << std::endl;
00206 } else {
00207 plist::Dictionary::const_iterator drobit = findEntry(it->first);
00208 plist::ObjectBase * drob = (drobit==end()) ? NULL : drobit->second;
00209 if(plist::Dictionary* dr = dynamic_cast<plist::Dictionary*>(drob)) {
00210 plist::Dictionary::const_iterator tyobit = dr->findEntry(".type");
00211 if(tyobit==dr->end())
00212 std::cerr << "WARNING: Driver dictionary lacking .type field for '" << it->first << "'" << std::endl;
00213 else if(tyobit->second->toString()==dd->type)
00214 continue;
00215 destroy(it->first);
00216 dr=NULL;
00217 }
00218 if(create(dd->type,it->first)==NULL)
00219 std::cerr << "ERROR: failed to instantiate driver named '" << it->first << "' with type '" << dd->type << "'" << std::endl;
00220 }
00221 }
00222
00223 plist::Dictionary::loadXML(node);
00224 }
00225
00226
00227
00228
00229
00230
00231 #endif