Registrar.h
Go to the documentation of this file.
00001 // kate: replace-tabs off; indent-width 4; indent-mode normal
00002 // vim: ts=4:sw=4:noexpandtab
00003 /*
00004 
00005 Copyright (c) 2010--2012,
00006 François Pomerleau and Stephane Magnenat, ASL, ETHZ, Switzerland
00007 You can contact the authors at <f dot pomerleau at gmail dot com> and
00008 <stephane at magnenat dot net>
00009 
00010 All rights reserved.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014     * Redistributions of source code must retain the above copyright
00015       notice, this list of conditions and the following disclaimer.
00016     * Redistributions in binary form must reproduce the above copyright
00017       notice, this list of conditions and the following disclaimer in the
00018       documentation and/or other materials provided with the distribution.
00019     * Neither the name of the <organization> nor the
00020       names of its contributors may be used to endorse or promote products
00021       derived from this software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY
00027 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00030 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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                                 // check that there was no unsed parameter
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                                 // parameter-less entry
00176                                 name = module.to<std::string>();
00177                         }
00178                         else
00179                         {
00180                                 // get parameters
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 } // namespace PointMatcherSupport
00234 
00235 #endif // __POINTMATCHER_REGISTRAR_H


upstream_src
Author(s):
autogenerated on Wed Sep 24 2014 10:42:00