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