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 #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; // second arg is 1st data arg.
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

Generated on Tue Mar 25 17:41:47 2008 for OrocosReal-TimeToolkit by  doxygen 1.5.3