MethodRepository.hpp

00001 /***************************************************************************
00002   tag: FMTC  do nov 2 13:06:08 CET 2006  MethodRepository.hpp
00003 
00004                         MethodRepository.hpp -  description
00005                            -------------------
00006     begin                : do november 02 2006
00007     copyright            : (C) 2006 FMTC
00008     email                : peter.soetens@fmtc.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
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; // second arg is 1st data arg.
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
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3