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