Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef __POINTMATCHER_REGISTRAR_H
00037 #define __POINTMATCHER_REGISTRAR_H
00038
00039 #include "Parametrizable.h"
00040 #include "PointMatcher.h"
00041 #include <boost/format.hpp>
00042 #include <boost/typeof/typeof.hpp>
00043
00044
00045 #ifdef SYSTEM_YAML_CPP
00046 namespace YAML
00047 {
00048 class Node;
00049 }
00050 #else
00051 namespace YAML_PM
00052 {
00053 class Node;
00054 }
00055 namespace YAML = YAML_PM;
00056 #endif // HAVE_YAML_CPP
00057
00058 namespace PointMatcherSupport
00059 {
00061 void getNameParamsFromYAML(const YAML::Node& module, std::string& name, Parametrizable::Parameters& params);
00062
00064 struct InvalidElement: std::runtime_error
00065 {
00066 InvalidElement(const std::string& reason);
00067 };
00068
00070 template<typename Interface>
00071 struct Registrar
00072 {
00073 public:
00074 typedef Interface TargetType;
00075
00077 struct ClassDescriptor
00078 {
00080 virtual ~ClassDescriptor() {}
00082 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const = 0;
00084 virtual const std::string description() const = 0;
00086 virtual const Parametrizable::ParametersDoc availableParameters() const = 0;
00087 };
00088
00090 template<typename C>
00091 struct GenericClassDescriptor: public ClassDescriptor
00092 {
00093 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const
00094 {
00095 C* instance(new C(params));
00096
00097
00098 for (BOOST_AUTO(it, params.begin()); it != params.end() ;++it)
00099 {
00100 if (instance->parametersUsed.find(it->first) == instance->parametersUsed.end())
00101 throw Parametrizable::InvalidParameter(
00102 (boost::format("Parameter %1% for module %2% was set but is not used") % it->first % className).str()
00103 );
00104 }
00105
00106 return instance;
00107 }
00108 virtual const std::string description() const
00109 {
00110 return C::description();
00111 }
00112 virtual const Parametrizable::ParametersDoc availableParameters() const
00113 {
00114 return C::availableParameters();
00115 }
00116 };
00117
00119 template<typename C>
00120 struct GenericClassDescriptorNoParam: public ClassDescriptor
00121 {
00122 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const
00123 {
00124 for (BOOST_AUTO(it, params.begin()); it != params.end() ;++it)
00125 throw Parametrizable::InvalidParameter(
00126 (boost::format("Parameter %1% was set but module %2% dos not use any parameter") % it->first % className).str()
00127 );
00128 return new C();
00129 }
00130 virtual const std::string description() const
00131 {
00132 return C::description();
00133 }
00134 virtual const Parametrizable::ParametersDoc availableParameters() const
00135 {
00136 return Parametrizable::ParametersDoc();
00137 }
00138 };
00139
00140 protected:
00141 typedef std::map<std::string, ClassDescriptor*> DescriptorMap;
00142 DescriptorMap classes;
00143
00144 public:
00146 ~Registrar()
00147 {
00148 for (BOOST_AUTO(it, classes.begin()); it != classes.end(); ++it)
00149 delete it->second;
00150 }
00152 void reg(const std::string &name, ClassDescriptor* descriptor)
00153 {
00154 classes[name] = descriptor;
00155 }
00156
00158 const ClassDescriptor* getDescriptor(const std::string& name) const
00159 {
00160 BOOST_AUTO(it, classes.find(name));
00161 if (it == classes.end())
00162 {
00163 std::cerr << "No element named " << name << " is registered. Known ones are:\n";
00164 dump(std::cerr);
00165 throw InvalidElement(
00166 (boost::format("Trying to instanciate unknown element %1% from registrar") % name).str()
00167 );
00168 }
00169 return it->second;
00170 }
00171
00173 Interface* create(const std::string& name, const Parametrizable::Parameters& params = Parametrizable::Parameters()) const
00174 {
00175 return getDescriptor(name)->createInstance(name, params);
00176 }
00177
00179 Interface* createFromYAML(const YAML::Node& module) const
00180 {
00181 std::string name;
00182 Parametrizable::Parameters params;
00183
00184 getNameParamsFromYAML(module, name, params);
00185
00186 return create(name, params);
00187 }
00188
00190 const std::string getDescription(const std::string& name) const
00191 {
00192 return getDescriptor(name)->description();
00193 }
00194
00196 void dump(std::ostream &stream) const
00197 {
00198 for (BOOST_AUTO(it, classes.begin()); it != classes.end(); ++it)
00199 stream << "- " << it->first << "\n";
00200 }
00201
00203 typename DescriptorMap::const_iterator begin() const
00204 {
00205 return classes.begin();
00206 }
00208 typename DescriptorMap::const_iterator end() const
00209 {
00210 return classes.end();
00211 }
00212 };
00213
00214 #define REG(name) name##Registrar
00215 #define DEF_REGISTRAR(name) PointMatcherSupport::Registrar< name > name##Registrar;
00216 #define DEF_REGISTRAR_IFACE(name, ifaceName) PointMatcherSupport::Registrar< ifaceName > name##Registrar;
00217 #define ADD_TO_REGISTRAR(name, elementName, element) { \
00218 typedef typename PointMatcherSupport::Registrar< name >::template GenericClassDescriptor< element > Desc; \
00219 name##Registrar.reg(# elementName, new Desc() ); \
00220 }
00221 #define ADD_TO_REGISTRAR_NO_PARAM(name, elementName, element) { \
00222 typedef typename PointMatcherSupport::Registrar< name >::template GenericClassDescriptorNoParam< element > Desc; \
00223 name##Registrar.reg(# elementName, new Desc() ); \
00224 }
00225 }
00226
00227 #endif // __POINTMATCHER_REGISTRAR_H