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 {
00046 template <class AbstractClass, class ConcreteClass>
00047 AbstractClass* Creator()
00048 {
00049 return new ConcreteClass();
00050 }
00051
00052 template <class AbstractClass, class ConcreteClass>
00053 void Destructor(AbstractClass*& obj)
00054 {
00055 if (obj == 0) { return; }
00056 ConcreteClass* tmp = dynamic_cast<ConcreteClass*>(obj);
00057 if (tmp == 0) { return; }
00058 delete obj;
00059 obj = 0;
00060 }
00061
00062 template <
00063 class AbstractClass,
00064 typename Identifier = std::string,
00065 typename Compare = std::less<Identifier>,
00066 typename Creator = AbstractClass* (*)(),
00067 typename Destructor = void (*)(AbstractClass*&)
00068 >
00069 class Factory
00070 {
00071 class FactoryEntry;
00072 public:
00073
00074 typedef std::map<Identifier, FactoryEntry> FactoryMap;
00075 typedef typename FactoryMap::iterator FactoryMapIt;
00076
00077 enum ReturnCode
00078 {
00079 FACTORY_OK,
00080 FACTORY_ERROR,
00081 ALREADY_EXISTS,
00082 NOT_FOUND,
00083 INVALID_ARG,
00084 UNKNOWN_ERROR
00085 };
00086
00087 bool hasFactory(const Identifier& id)
00088 {
00089 if (m_creators.count(id) == 0) { return false; }
00090 return true;
00091 }
00092
00093 std::vector<Identifier> getIdentifiers()
00094 {
00095 std::vector<Identifier> idlist;
00096 idlist.reserve(m_creators.size());
00097
00098 FactoryMapIt it(m_creators.begin());
00099 FactoryMapIt it_end(m_creators.end());
00100
00101 while (it != it_end)
00102 {
00103 idlist.push_back(it->first);
00104 ++it;
00105 }
00106 return idlist;
00107 }
00108
00109 ReturnCode addFactory(const Identifier& id,
00110 Creator creator,
00111 Destructor destructor)
00112 {
00113 if (creator == 0 || destructor == 0) { return INVALID_ARG; }
00114 if (m_creators.count(id) != 0) { return ALREADY_EXISTS; }
00115 FactoryEntry f(creator, destructor);
00116 m_creators[id] = f;
00117 return FACTORY_OK;
00118 }
00119
00120 ReturnCode removeFactory(const Identifier& id)
00121 {
00122 if (m_creators.count(id) == 0) { return NOT_FOUND; }
00123
00124 m_creators.erase(id);
00125 return FACTORY_OK;
00126 }
00127
00128 AbstractClass* createObject(const Identifier& id)
00129 {
00130 if (m_creators.count(id) == 0) { return 0; }
00131 return m_creators[id].creator_();
00132 }
00133
00134 void deleteObject(const Identifier& id, AbstractClass*& obj)
00135 {
00136 if (m_creators.count(id) == 0) { return; }
00137 m_creators[id].destructor_(obj);
00138 }
00139
00140 void deleteObject(AbstractClass*& obj)
00141 {
00142 FactoryMapIt it(m_creators.begin());
00143 FactoryMapIt it_end(m_creators.end());
00144
00145 while (it != it_end)
00146 {
00147 it->second.destructor_(obj);
00148 ++it;
00149 }
00150 }
00151
00152 private:
00153 class FactoryEntry
00154 {
00155 public:
00156 explicit FactoryEntry()
00157 {
00158 }
00159 FactoryEntry(Creator creator, Destructor destructor)
00160 : creator_(creator), destructor_(destructor)
00161 {
00162 }
00163 Creator creator_;
00164 Destructor destructor_;
00165 };
00166 FactoryMap m_creators;
00167 };
00168
00169
00170
00171 template <
00172 class AbstractClass,
00173 typename Identifier = std::string,
00174 typename Compare = std::less<Identifier>,
00175 typename Creator = AbstractClass* (*)(),
00176 typename Destructor = void (*)(AbstractClass*&)
00177 >
00178 class GlobalFactory
00179 : public Factory<AbstractClass, Identifier, Compare, Creator, Destructor>,
00180 public coil::Singleton<GlobalFactory<AbstractClass,
00181 Identifier,
00182 Compare,
00183 Creator,
00184 Destructor> >
00185 {
00186 public:
00187
00188 private:
00189 GlobalFactory(){}
00190 ~GlobalFactory(){}
00191 friend class Singleton<GlobalFactory>;
00192 };
00193
00194 };
00195 #endif // COIL_FACTORY_H