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 #endif // HAVE_YAML_CPP
00056
00057 namespace PointMatcherSupport
00058 {
00059 #ifdef SYSTEM_YAML_CPP
00060 namespace YAML = ::YAML;
00061 #else
00062 namespace YAML = ::YAML_PM;
00063 #endif
00064
00066 void getNameParamsFromYAML(const YAML::Node& module, std::string& name, Parametrizable::Parameters& params);
00067
00069 struct InvalidElement: std::runtime_error
00070 {
00071 InvalidElement(const std::string& reason);
00072 };
00073
00075 template<typename Interface>
00076 struct Registrar
00077 {
00078 public:
00079 typedef Interface TargetType;
00080
00082 struct ClassDescriptor
00083 {
00085 virtual ~ClassDescriptor() {}
00087 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const = 0;
00089 virtual const std::string description() const = 0;
00091 virtual const Parametrizable::ParametersDoc availableParameters() const = 0;
00092 };
00093
00095 template<typename C>
00096 struct GenericClassDescriptor: public ClassDescriptor
00097 {
00098 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const
00099 {
00100 C* instance(new C(params));
00101
00102
00103 for (BOOST_AUTO(it, params.begin()); it != params.end() ;++it)
00104 {
00105 if (instance->parametersUsed.find(it->first) == instance->parametersUsed.end())
00106 throw Parametrizable::InvalidParameter(
00107 (boost::format("Parameter %1% for module %2% was set but is not used") % it->first % className).str()
00108 );
00109 }
00110
00111 return instance;
00112 }
00113 virtual const std::string description() const
00114 {
00115 return C::description();
00116 }
00117 virtual const Parametrizable::ParametersDoc availableParameters() const
00118 {
00119 return C::availableParameters();
00120 }
00121 };
00122
00124 template<typename C>
00125 struct GenericClassDescriptorNoParam: public ClassDescriptor
00126 {
00127 virtual Interface* createInstance(const std::string& className, const Parametrizable::Parameters& params) const
00128 {
00129 for (BOOST_AUTO(it, params.begin()); it != params.end() ;++it)
00130 throw Parametrizable::InvalidParameter(
00131 (boost::format("Parameter %1% was set but module %2% dos not use any parameter") % it->first % className).str()
00132 );
00133 return new C();
00134 }
00135 virtual const std::string description() const
00136 {
00137 return C::description();
00138 }
00139 virtual const Parametrizable::ParametersDoc availableParameters() const
00140 {
00141 return Parametrizable::ParametersDoc();
00142 }
00143 };
00144
00145 protected:
00146 typedef std::map<std::string, ClassDescriptor*> DescriptorMap;
00147 DescriptorMap classes;
00148
00149 public:
00151 ~Registrar()
00152 {
00153 for (BOOST_AUTO(it, classes.begin()); it != classes.end(); ++it)
00154 delete it->second;
00155 }
00157 void reg(const std::string &name, ClassDescriptor* descriptor)
00158 {
00159 classes[name] = descriptor;
00160 }
00161
00163 const ClassDescriptor* getDescriptor(const std::string& name) const
00164 {
00165 BOOST_AUTO(it, classes.find(name));
00166 if (it == classes.end())
00167 {
00168 std::cerr << "No element named " << name << " is registered. Known ones are:\n";
00169 dump(std::cerr);
00170 throw InvalidElement(
00171 (boost::format("Trying to instanciate unknown element %1% from registrar") % name).str()
00172 );
00173 }
00174 return it->second;
00175 }
00176
00178 Interface* create(const std::string& name, const Parametrizable::Parameters& params = Parametrizable::Parameters()) const
00179 {
00180 return getDescriptor(name)->createInstance(name, params);
00181 }
00182
00184 Interface* createFromYAML(const YAML::Node& module) const
00185 {
00186 std::string name;
00187 Parametrizable::Parameters params;
00188
00189 getNameParamsFromYAML(module, name, params);
00190
00191 return create(name, params);
00192 }
00193
00195 const std::string getDescription(const std::string& name) const
00196 {
00197 return getDescriptor(name)->description();
00198 }
00199
00201 void dump(std::ostream &stream) const
00202 {
00203 for (BOOST_AUTO(it, classes.begin()); it != classes.end(); ++it)
00204 stream << "- " << it->first << "\n";
00205 }
00206
00208 typename DescriptorMap::const_iterator begin() const
00209 {
00210 return classes.begin();
00211 }
00213 typename DescriptorMap::const_iterator end() const
00214 {
00215 return classes.end();
00216 }
00217 };
00218
00219 #define REG(name) name##Registrar
00220 #define DEF_REGISTRAR(name) PointMatcherSupport::Registrar< name > name##Registrar;
00221 #define DEF_REGISTRAR_IFACE(name, ifaceName) PointMatcherSupport::Registrar< ifaceName > name##Registrar;
00222 #define ADD_TO_REGISTRAR(name, elementName, element) { \
00223 typedef typename PointMatcherSupport::Registrar< name >::template GenericClassDescriptor< element > Desc; \
00224 name##Registrar.reg(# elementName, new Desc() ); \
00225 }
00226 #define ADD_TO_REGISTRAR_NO_PARAM(name, elementName, element) { \
00227 typedef typename PointMatcherSupport::Registrar< name >::template GenericClassDescriptorNoParam< element > Desc; \
00228 name##Registrar.reg(# elementName, new Desc() ); \
00229 }
00230 }
00231
00232 #endif // __POINTMATCHER_REGISTRAR_H