Sirikata
|
00001 /* Sirikata Utilities -- Sirikata Utilities 00002 * Factory.hpp 00003 * 00004 * Copyright (c) 2009, Daniel Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifndef _SIRIKATA_FACTORY_HPP_ 00034 #define _SIRIKATA_FACTORY_HPP_ 00035 00036 namespace Sirikata { 00037 00038 class FactoryMissingConstructorException : public std::exception { 00039 public: 00040 FactoryMissingConstructorException(const String& _name) 00041 : name(_name), 00042 what_msg(new String()) 00043 {} 00044 FactoryMissingConstructorException(const FactoryMissingConstructorException& rhs) 00045 : name(rhs.name), 00046 what_msg(new String(*(rhs.what_msg))) 00047 {} 00048 virtual ~FactoryMissingConstructorException() throw() { 00049 delete what_msg; 00050 } 00051 00052 char const* what() const throw() { 00053 if (what_msg->empty()) 00054 (*what_msg) = "Factory missing constructor: " + name + " not registered in the factory."; 00055 return what_msg->c_str(); 00056 } 00057 private: 00058 const String name; 00059 String* what_msg; 00060 }; 00061 00062 template<class T, class Ftype> 00063 class FactoryImpl { 00064 00065 typedef std::tr1::unordered_map<String,Ftype> ConstructorMap; 00066 ConstructorMap mConstructors; 00067 template <class U> static U* noop(U*) { 00068 return NULL; 00069 } 00070 template <class U> static U noop(const U&) { 00071 return U(); 00072 } 00073 static T staticNoop() { 00074 T temp=T(); 00075 return noop(temp); 00076 } 00077 Ftype mNoop; 00078 String mDefault; 00079 public: 00080 FactoryImpl():mNoop(std::tr1::bind(&FactoryImpl<T,Ftype>::staticNoop)){} 00081 bool unregisterConstructor(const String& name) { 00082 00083 typename ConstructorMap::iterator where=mConstructors.find(name); 00084 if (where==mConstructors.end()) 00085 return false; 00086 mConstructors.erase(where); 00087 if (mDefault==name) { 00088 mDefault=String(); 00089 } 00090 return true; 00091 } 00092 bool registerConstructor(const String& name, 00093 const Ftype &constructor, 00094 bool isDefault=false) { 00095 if (mConstructors.find(name)!=mConstructors.end()) 00096 return false; 00097 mConstructors[name]=constructor; 00098 if (isDefault) { 00099 mDefault=name; 00100 } 00101 return true; 00102 } 00103 const String& getDefault() const { 00104 return mDefault; 00105 } 00106 bool hasConstructor(const String&name)const { 00107 return mConstructors.find(name) != mConstructors.end(); 00108 } 00109 typedef std::list<String> ConstructorNameList; 00110 ConstructorNameList getNames() const { 00111 ConstructorNameList result; 00112 for(typename ConstructorMap::const_iterator it = mConstructors.begin(); it != mConstructors.end(); it++) 00113 result.push_back(it->first); 00114 return result; 00115 } 00116 00117 const Ftype &getConstructorOrDefault(const String&name)const{ 00118 typename ConstructorMap::const_iterator where=mConstructors.find(name); 00119 if (where==mConstructors.end()) { 00120 if (name.length()==0&&mDefault.length()) { 00121 return getConstructor(mDefault); 00122 } 00123 return mNoop; 00124 } 00125 return where->second; 00126 } 00127 00128 // Gets a specific constructor and throws a 00129 // FactoryMissingConstructorException if it can't be found 00130 const Ftype& getConstructor(const String&name) const { 00131 if (!hasConstructor(name)) 00132 throw FactoryMissingConstructorException(name); 00133 return getConstructorOrDefault(name); 00134 } 00135 00136 const Ftype& getDefaultConstructor()const{ 00137 return getConstructor(mDefault); 00138 } 00139 }; 00140 00141 template <class T>class Factory:public FactoryImpl<T,std::tr1::function<T()> >{}; 00142 00143 template <class T, typename A>class Factory1:public FactoryImpl<T,std::tr1::function<T(A)> >{}; 00144 00145 template <class T, typename A, typename B>class Factory2:public FactoryImpl<T,std::tr1::function<T(A,B)> >{}; 00146 00147 template <class T, typename A, typename B, typename C>class Factory3:public FactoryImpl<T,std::tr1::function<T(A,B,C)> >{}; 00148 00149 template <class T, typename A, typename B, typename C, typename D>class Factory4:public FactoryImpl<T,std::tr1::function<T(A,B,C,D)> >{}; 00150 00151 template <class T, typename A, typename B, typename C, typename D, typename E>class Factory5:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E)> >{}; 00152 00153 template <class T, typename A, typename B, typename C, typename D, typename E, typename F>class Factory6:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E,F)> >{}; 00154 00155 } 00156 #endif