00001
00020 #ifndef COIL_FACTORY_H
00021 #define COIL_FACTORY_H
00022
00023 #include <string>
00024 #include <map>
00025 #include <algorithm>
00026 #include <vector>
00027 #include <coil/Singleton.h>
00028
00029
00030 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
00031 # ifdef LIBRARY_EXPORTS
00032 # define EXTERN
00033 # define DLL_PLUGIN __declspec(dllexport)
00034 # else
00035 # define EXTERN extern
00036 # define DLL_PLUGIN __declspec(dllimport)
00037 # endif
00038 #else
00039 # define DLL_PLUGIN
00040 # define EXTERN
00041 #endif
00042
00043
00044 namespace coil
00045 {
00057 template <class AbstractClass, class ConcreteClass>
00058 AbstractClass* Creator()
00059 {
00060 return new ConcreteClass();
00061 }
00062
00074 template <class AbstractClass, class ConcreteClass>
00075 void Destructor(AbstractClass*& obj)
00076 {
00077 if (obj == 0) { return; }
00078 ConcreteClass* tmp = dynamic_cast<ConcreteClass*>(obj);
00079 if (tmp == 0) { return; }
00080 delete obj;
00081 obj = 0;
00082 }
00083
00097 template <
00098 class AbstractClass,
00099 typename Identifier = std::string,
00100 typename Compare = std::less<Identifier>,
00101 typename Creator = AbstractClass* (*)(),
00102 typename Destructor = void (*)(AbstractClass*&)
00103 >
00104 class Factory
00105 {
00106 class FactoryEntry;
00107 public:
00108
00109 typedef std::map<Identifier, FactoryEntry> FactoryMap;
00110 typedef typename FactoryMap::iterator FactoryMapIt;
00111
00112 enum ReturnCode
00113 {
00114 FACTORY_OK,
00115 FACTORY_ERROR,
00116 ALREADY_EXISTS,
00117 NOT_FOUND,
00118 INVALID_ARG,
00119 UNKNOWN_ERROR
00120 };
00121
00145 bool hasFactory(const Identifier& id)
00146 {
00147 if (m_creators.count(id) == 0) { return false; }
00148 return true;
00149 }
00150
00170 std::vector<Identifier> getIdentifiers()
00171 {
00172 std::vector<Identifier> idlist;
00173 idlist.reserve(m_creators.size());
00174
00175 FactoryMapIt it(m_creators.begin());
00176 FactoryMapIt it_end(m_creators.end());
00177
00178 while (it != it_end)
00179 {
00180 idlist.push_back(it->first);
00181 ++it;
00182 }
00183 return idlist;
00184 }
00185
00217 ReturnCode addFactory(const Identifier& id,
00218 Creator creator,
00219 Destructor destructor)
00220 {
00221 if (creator == 0 || destructor == 0) { return INVALID_ARG; }
00222 if (m_creators.count(id) != 0) { return ALREADY_EXISTS; }
00223 FactoryEntry f(creator, destructor);
00224 m_creators[id] = f;
00225 return FACTORY_OK;
00226 }
00227
00253 ReturnCode removeFactory(const Identifier& id)
00254 {
00255 if (m_creators.count(id) == 0) { return NOT_FOUND; }
00256
00257 m_creators.erase(id);
00258 return FACTORY_OK;
00259 }
00260
00284 AbstractClass* createObject(const Identifier& id)
00285 {
00286 if (m_creators.count(id) == 0) { return 0; }
00287 return m_creators[id].creator_();
00288 }
00289
00311 void deleteObject(const Identifier& id, AbstractClass*& obj)
00312 {
00313 if (m_creators.count(id) == 0) { return; }
00314 m_creators[id].destructor_(obj);
00315 }
00316
00336 void deleteObject(AbstractClass*& obj)
00337 {
00338 FactoryMapIt it(m_creators.begin());
00339 FactoryMapIt it_end(m_creators.end());
00340
00341 while (it != it_end)
00342 {
00343 it->second.destructor_(obj);
00344 ++it;
00345 }
00346 }
00347
00348 private:
00349
00363 class FactoryEntry
00364 {
00365 public:
00366 explicit FactoryEntry()
00367 {
00368 }
00369
00391 FactoryEntry(Creator creator, Destructor destructor)
00392 : creator_(creator), destructor_(destructor)
00393 {
00394 }
00395 Creator creator_;
00396 Destructor destructor_;
00397 };
00398 FactoryMap m_creators;
00399 };
00400
00401
00402
00416 template <
00417 class AbstractClass,
00418 typename Identifier = std::string,
00419 typename Compare = std::less<Identifier>,
00420 typename Creator = AbstractClass* (*)(),
00421 typename Destructor = void (*)(AbstractClass*&)
00422 >
00423 class GlobalFactory
00424 : public Factory<AbstractClass, Identifier, Compare, Creator, Destructor>,
00425 public coil::Singleton<GlobalFactory<AbstractClass,
00426 Identifier,
00427 Compare,
00428 Creator,
00429 Destructor> >
00430 {
00431 public:
00432
00433 private:
00449 GlobalFactory(){}
00450
00466 ~GlobalFactory(){}
00467
00468 friend class Singleton<GlobalFactory>;
00469 };
00470
00471 };
00472 #endif // COIL_FACTORY_H