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