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
00037
00038
00039 #ifndef ORO_METHOD_REPOSITORY_HPP
00040 #define ORO_METHOD_REPOSITORY_HPP
00041
00042 #include "OperationFactory.hpp"
00043 #include "LocalMethod.hpp"
00044 #include "DataSourceArgsMethod.hpp"
00045 #include "MethodC.hpp"
00046 #include <boost/shared_ptr.hpp>
00047 #include <boost/static_assert.hpp>
00048 #include <boost/type_traits/function_traits.hpp>
00049
00050 namespace RTT
00051 {
00057 class MethodRepository
00058 : public OperationFactory<DataSourceBase*>
00059 {
00060 template<class T>
00061 inline T* getpointer(T& t) {
00062 return &t;
00063 }
00064 template<class T>
00065 inline T* getpointer(T* t) {
00066 return t;
00067 }
00068
00069 protected:
00070 std::map<std::string,boost::shared_ptr<ActionInterface> > simplemethods;
00071 public:
00072 typedef MethodFactory Factory;
00073
00074 ~MethodRepository()
00075 {
00076 clear();
00077 }
00078
00082 void clear() {
00083 while ( !simplemethods.empty() ) {
00084 simplemethods.erase( simplemethods.begin() );
00085 }
00086 OperationFactory<DataSourceBase*>::clear();
00087 }
00088
00093 std::vector<std::string> getMethods() const {
00094 return keys( simplemethods );
00095 }
00096
00101 bool hasMethod(const std::string& name) const {
00102 return simplemethods.count(name) == 1;
00103 }
00104
00114 template<class MethodT>
00115 bool addMethod( MethodT* meth )
00116 {
00117 Logger::In in("MethodRepository");
00118 if ( simplemethods.count( meth->getName() ) ) {
00119 log(Error) << "Failed to addMethod: '"<< meth->getName() <<"' already added." <<endlog();
00120 return false;
00121 }
00122 if ( meth->getName().empty() || !meth->ready() ) {
00123 log(Error) << "Failed to addMethod: '"<< meth->getName() <<"' was not ready() or has no name." <<endlog();
00124 return false;
00125 }
00126 simplemethods[meth->getName()] = meth->getMethodImpl();
00127 log(Debug) << "Added Method: '"<< meth->getName() <<"'." <<endlog();
00128 return true;
00129 }
00130
00142 template<class Signature>
00143 boost::shared_ptr<ActionInterface> getMethod( std::string name )
00144 {
00145 Logger::In in("MethodRepository::getMethod");
00146 if ( simplemethods.count(name) ) {
00147 if ( boost::dynamic_pointer_cast< detail::MethodBase<Signature> >(simplemethods[name]) )
00148 return simplemethods[name];
00149 else
00150 log(Error) << "Method '"<< name <<"' found, but has wrong Signature."<<endlog();
00151 return boost::shared_ptr<ActionInterface>();
00152 }
00153 log(Warning) << "No such method: "<< name <<endlog();
00154 return boost::shared_ptr<ActionInterface>();
00155 }
00156
00157
00169 template<class MethodT>
00170 bool addMethod( MethodT meth, const char* description)
00171 {
00172 typedef typename boost::remove_pointer<MethodT>::type MethodVT;
00173 typedef typename boost::add_pointer<MethodVT>::type MethodPT;
00174 BOOST_STATIC_ASSERT( boost::function_traits<typename MethodVT::Signature>::arity == 0 );
00175
00176 MethodPT c = this->getpointer(meth);
00177 typedef typename MethodVT::Signature Sig;
00178 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c->getMethodImpl().get() );
00179 if ( !lm ) {
00180 log(Error) << "Failed to addMethod: '"<< c->getName() <<"' is not a local method." <<endlog();
00181 return false;
00182 }
00183 if ( this->addMethod( c ) == false )
00184 return false;
00185 this->add( c->getName(), new detail::OperationFactoryPart0<DataSourceBase*, detail::DataSourceArgsMethod<Sig> >(
00186 detail::DataSourceArgsMethod<Sig>( lm->getMethodFunction()), description) );
00187 return true;
00188 }
00189
00203 template<class MethodT>
00204 bool addMethod( MethodT meth, const char* description,
00205 const char* arg1, const char* arg1_description)
00206 {
00207 typedef typename boost::remove_pointer<MethodT>::type MethodVT;
00208 typedef typename boost::add_pointer<MethodVT>::type MethodPT;
00209 BOOST_STATIC_ASSERT( boost::function_traits<typename MethodVT::Signature>::arity == 1 );
00210
00211 MethodPT c = this->getpointer(meth);
00212 typedef typename MethodVT::Signature Sig;
00213 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c->getMethodImpl().get() );
00214 if ( !lm ) {
00215 log(Error) << "Failed to addMethod: '"<< c->getName() <<"' is not a local method." <<endlog();
00216 return false;
00217 }
00218 if ( this->addMethod( c ) == false )
00219 return false;
00220 this->add( c->getName(), new detail::OperationFactoryPart1<DataSourceBase*, detail::DataSourceArgsMethod<Sig> >(
00221 detail::DataSourceArgsMethod<Sig>(lm->getMethodFunction()),
00222 description, arg1, arg1_description) );
00223 return true;
00224 }
00225
00241 template<class MethodT>
00242 bool addMethod( MethodT meth, const char* description,
00243 const char* arg1, const char* arg1_description,
00244 const char* arg2, const char* arg2_description)
00245 {
00246 typedef typename boost::remove_pointer<MethodT>::type MethodVT;
00247 typedef typename boost::add_pointer<MethodVT>::type MethodPT;
00248 BOOST_STATIC_ASSERT( boost::function_traits<typename MethodVT::Signature>::arity == 2 );
00249
00250 MethodPT c = this->getpointer(meth);
00251 typedef typename MethodVT::Signature Sig;
00252 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c->getMethodImpl().get() );
00253 if ( !lm ) {
00254 log(Error) << "Failed to addMethod: '"<< c->getName() <<"' is not a local method." <<endlog();
00255 return false;
00256 }
00257 if ( this->addMethod( c ) == false )
00258 return false;
00259 this->add( c->getName(), new detail::OperationFactoryPart2<DataSourceBase*, detail::DataSourceArgsMethod<Sig> >(
00260 detail::DataSourceArgsMethod<Sig>(lm->getMethodFunction()),
00261 description,
00262 arg1, arg1_description,
00263 arg2, arg2_description) );
00264 return true;
00265 }
00266
00284 template<class MethodT>
00285 bool addMethod( MethodT meth, const char* description,
00286 const char* arg1, const char* arg1_description,
00287 const char* arg2, const char* arg2_description,
00288 const char* arg3, const char* arg3_description)
00289 {
00290 typedef typename boost::remove_pointer<MethodT>::type MethodVT;
00291 typedef typename boost::add_pointer<MethodVT>::type MethodPT;
00292 BOOST_STATIC_ASSERT( boost::function_traits<typename MethodVT::Signature>::arity == 3 );
00293
00294 MethodPT c = this->getpointer(meth);
00295 typedef typename MethodVT::Signature Sig;
00296 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c->getMethodImpl().get() );
00297 if ( !lm ) {
00298 log(Error) << "Failed to addMethod: '"<< c->getName() <<"' is not a local method." <<endlog();
00299 return false;
00300 }
00301 if ( this->addMethod( c ) == false )
00302 return false;
00303 this->add( c->getName(), new detail::OperationFactoryPart3<DataSourceBase*, detail::DataSourceArgsMethod<Sig> >(
00304 detail::DataSourceArgsMethod<Sig>(lm->getMethodFunction()),
00305 description,
00306 arg1, arg1_description,
00307 arg2, arg2_description,
00308 arg3, arg3_description) );
00309 return true;
00310 }
00311
00331 template<class MethodT>
00332 bool addMethod( MethodT meth, const char* description,
00333 const char* arg1, const char* arg1_description,
00334 const char* arg2, const char* arg2_description,
00335 const char* arg3, const char* arg3_description,
00336 const char* arg4, const char* arg4_description)
00337 {
00338 typedef typename boost::remove_pointer<MethodT>::type MethodVT;
00339 typedef typename boost::add_pointer<MethodVT>::type MethodPT;
00340 BOOST_STATIC_ASSERT( boost::function_traits<typename MethodVT::Signature>::arity == 4 );
00341
00342 MethodPT c = this->getpointer(meth);
00343 typedef typename MethodVT::Signature Sig;
00344 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c->getMethodImpl().get() );
00345 if ( !lm ) {
00346 log(Error) << "Failed to addMethod: '"<< c->getName() <<"' is not a local method." <<endlog();
00347 return false;
00348 }
00349 if ( this->addMethod( c ) == false )
00350 return false;
00351 this->add( c->getName(), new detail::OperationFactoryPart4<DataSourceBase*, detail::DataSourceArgsMethod<Sig> >(
00352 detail::DataSourceArgsMethod<Sig>(lm->getMethodFunction()),
00353 description,
00354 arg1, arg1_description,
00355 arg2, arg2_description,
00356 arg3, arg3_description,
00357 arg4, arg4_description) );
00358 return true;
00359 }
00360
00366 template<class MethodT,class CompT>
00367 bool addMethodDS( DataSource< boost::weak_ptr<CompT> >* wp, MethodT c, const char* description)
00368 {
00369 using namespace detail;
00370 typedef typename MethodT::Signature Sig;
00371 if ( this->hasMember(c.getName() ) )
00372 return false;
00373 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c.getMethodImpl().get() );
00374 if ( !lm )
00375 return false;
00376 typedef FunctorDataSourceDS0<CompT, boost::function<Sig> > FunctorT;
00377 typedef detail::DataSourceArgsMethod<Sig, FunctorT> DSMeth;
00378
00379 this->add( c.getName(), new detail::OperationFactoryPart0<DataSourceBase*, DSMeth>(
00380 DSMeth( typename FunctorT::shared_ptr(new FunctorT(wp, lm->getMethodFunction()))),
00381 description));
00382 return true;
00383 }
00384
00390 template<class MethodT,class CompT>
00391 bool addMethodDS( DataSource< boost::weak_ptr<CompT> >* wp, MethodT c, const char* description,
00392 const char* a1, const char* d1)
00393 {
00394 using namespace detail;
00395 typedef typename MethodT::Signature Sig;
00396 if ( this->hasMember(c.getName() ) )
00397 return false;
00398 const detail::LocalMethod<Sig>* lm = dynamic_cast< const detail::LocalMethod<Sig>* >( c.getMethodImpl().get() );
00399 if ( !lm )
00400 return false;
00401 typedef typename MethodT::traits::arg2_type arg1_type;
00402 typedef FunctorDataSourceDS1<CompT, boost::function<Sig>, arg1_type > FunctorT;
00403 typedef detail::DataSourceArgsMethod<Sig, FunctorT> DSMeth;
00404 this->add( c.getName(), new detail::OperationFactoryPart1<DataSourceBase*, DSMeth, arg1_type >(
00405 DSMeth( typename FunctorT::shared_ptr(new FunctorT(wp, lm->getMethodFunction()))),
00406 description, a1, d1));
00407 return true;
00408 }
00409
00419 DataSourceBase* getMethod( std::string name,
00420 const std::vector<DataSourceBase::shared_ptr>& args) const
00421 {
00422 return this->produce(name, args);
00423 }
00424
00433 MethodC create(std::string name) {
00434 return MethodC( this, name );
00435 }
00436
00440 bool resetMethod(std::string name, ActionInterface::shared_ptr impl)
00441 {
00442 if (!hasMethod(name))
00443 return false;
00444 simplemethods[name] = impl;
00445 return true;
00446 }
00447 };
00448 }
00449
00450
00451 #endif