CommandRepository.hpp

00001 /***************************************************************************
00002   tag: FMTC  do nov 2 13:06:10 CET 2006  CommandRepository.hpp
00003 
00004                         CommandRepository.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_COMMAND_REPOSITORY_HPP
00040 #define ORO_COMMAND_REPOSITORY_HPP
00041 
00042 #include "DataSourceArgsCommand.hpp"
00043 #include "OperationFactory.hpp"
00044 #include "CommandC.hpp"
00045 #include "LocalCommand.hpp"
00046 #ifdef ORO_REMOTING
00047 #include "RemoteCommand.hpp"
00048 #endif
00049 #include "Logger.hpp"
00050 #include <boost/static_assert.hpp>
00051 #include <boost/type_traits/function_traits.hpp>
00052 
00053 namespace RTT
00054 {
00060     class RTT_API CommandRepository
00061         : public OperationFactory<DispatchInterface*>
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         typedef std::map<std::string,DispatchInterface*> SimpleCommands;
00073         SimpleCommands simplecommands;
00074     public:
00075         typedef CommandFactory Factory;
00076 
00077         ~CommandRepository();
00078 
00089         template<class Signature>
00090         DispatchInterface* getCommand( std::string name )
00091         {
00092             Logger::In in("CommandRepository::getCommand");
00093             if ( simplecommands.count(name) ) {
00094                 if ( dynamic_cast< detail::CommandBase<Signature>* >(simplecommands[name]) )
00095                     return simplecommands[name]->clone();
00096                 else
00097                     log(Error) << "Command '"<< name <<"' found, but has wrong Signature."<<endlog();
00098                 return 0;
00099             }
00100 
00101 #ifdef ORO_REMOTING
00102             if ( this->hasMember(name ) ) {
00103                 return new detail::RemoteCommand<Signature>(this, name);
00104             }
00105 #endif
00106             log(Warning) << "No such command: "<< name <<endlog();
00107             return 0;
00108         }
00109 
00113         void clear();
00114 
00119         std::vector<std::string> getCommands() const;
00120 
00125         bool hasCommand(const std::string& name) const;
00126 
00130         void removeCommand(const std::string& name);
00131 
00141         template<class CommandT>
00142         bool addCommand( CommandT* com )
00143         {
00144             Logger::In in("CommandRepository");
00145             if ( simplecommands.count( com->getName() ) ) {
00146                 log(Error) << "Failed to addCommand: '"<< com->getName() <<"' already added." <<endlog();
00147                 return false;
00148             }
00149             if (  com->getName().empty() || !com->ready() ) {
00150                 log(Error) << "Failed to addCommand: '"<< com->getName() <<"' was not ready() or has no name." <<endlog();
00151                 return false;
00152             }
00153             simplecommands[com->getName()] = com->getCommandImpl()->clone();
00154             this->add(com->getName(), 0);
00155             return true;
00156         }
00157 
00158 
00167         template<class CommandT>
00168         bool addCommand( CommandT com, const char* description)
00169         {
00170             Logger::In in("CommandRepository");
00171             typedef typename boost::remove_pointer<CommandT>::type CommandVT;
00172             typedef typename boost::add_pointer<CommandVT>::type CommandPT;
00173             typedef typename CommandVT::Signature ComSig;
00174             BOOST_STATIC_ASSERT( boost::function_traits<typename CommandVT::Signature>::arity == 0 );
00175 
00176             CommandPT c = this->getpointer(com);
00177             detail::LocalCommand<ComSig>* lc = dynamic_cast<detail::LocalCommand<ComSig>*>( c->getCommandImpl() );
00178             // We can only add local commands.
00179             if ( !lc ) {
00180                 log(Error) << "Failed to addCommand: '"<< c->getName() <<"' is not a local command." <<endlog();
00181                 return false;
00182             }
00183             // First add the command to the normal interface.
00184             if ( this->addCommand( c ) == false )
00185                 return false;
00186             // Next, add it to the Command from 'DataSource' interface.
00187             this->add( c->getName(), new detail::OperationFactoryPart0<DispatchInterface*, detail::DataSourceArgsCommand<ComSig> >(
00188                   detail::DataSourceArgsCommand<ComSig>(lc->getCommandFunction(),
00189                                         lc->getConditionFunction(),
00190                                         lc->getCommandProcessor(), lc->isInverted() ), description) );
00191             return true;
00192         }
00193 
00206         template<class CommandT>
00207         bool addCommand( CommandT com, const char* description,
00208                          const char* arg1, const char* arg1_description)
00209         {
00210             Logger::In in("CommandRepository");
00211             typedef typename boost::remove_pointer<CommandT>::type CommandVT;
00212             typedef typename boost::add_pointer<CommandVT>::type CommandPT;
00213             typedef typename CommandVT::Signature ComSig;
00214             BOOST_STATIC_ASSERT( boost::function_traits<typename CommandVT::Signature>::arity == 1 );
00215 
00216             CommandPT c = this->getpointer(com);
00217             detail::LocalCommand<ComSig>* lc = dynamic_cast<detail::LocalCommand<ComSig>*>( c->getCommandImpl() );
00218             if ( !lc ) {
00219                 log(Error) << "Failed to addCommand: '"<< c->getName() <<"' is not a local command." <<endlog();
00220                 return false;
00221             }
00222             if ( this->addCommand( c ) == false )
00223                 return false;
00224             this->add( c->getName(), new detail::OperationFactoryPart1<DispatchInterface*, detail::DataSourceArgsCommand<ComSig> >(
00225                   detail::DataSourceArgsCommand<ComSig>(lc->getCommandFunction(),
00226                                         lc->getConditionFunction(),
00227                                         lc->getCommandProcessor(), lc->isInverted() ),
00228                   description, arg1, arg1_description) );
00229             return true;
00230         }
00231 
00246         template<class CommandT>
00247         bool addCommand( CommandT com, const char* description,
00248                          const char* arg1, const char* arg1_description,
00249                          const char* arg2, const char* arg2_description)
00250         {
00251             Logger::In in("CommandRepository");
00252             typedef typename boost::remove_pointer<CommandT>::type CommandVT;
00253             typedef typename boost::add_pointer<CommandVT>::type CommandPT;
00254             typedef typename CommandVT::Signature ComSig;
00255             BOOST_STATIC_ASSERT( boost::function_traits<typename CommandVT::Signature>::arity == 2 );
00256 
00257             CommandPT c = this->getpointer(com);
00258             detail::LocalCommand<ComSig>* lc = dynamic_cast<detail::LocalCommand<ComSig>*>( c->getCommandImpl() );
00259             if ( !lc ) {
00260                 log(Error) << "Failed to addCommand: '"<< c->getName() <<"' is not a local command." <<endlog();
00261                 return false;
00262             }
00263             if ( this->addCommand( c ) == false )
00264                 return false;
00265             this->add( c->getName(), new detail::OperationFactoryPart2<DispatchInterface*, detail::DataSourceArgsCommand<ComSig> >(
00266                   detail::DataSourceArgsCommand<ComSig>(lc->getCommandFunction(),
00267                                         lc->getConditionFunction(),
00268                                         lc->getCommandProcessor(), lc->isInverted() ),
00269                   description, arg1, arg1_description,
00270                   arg2, arg2_description) );
00271             return true;
00272         }
00273 
00274 
00291         template<class CommandT>
00292         bool addCommand( CommandT com, const char* description,
00293                          const char* arg1, const char* arg1_description,
00294                          const char* arg2, const char* arg2_description,
00295                          const char* arg3, const char* arg3_description)
00296         {
00297             Logger::In in("CommandRepository");
00298             typedef typename boost::remove_pointer<CommandT>::type CommandVT;
00299             typedef typename boost::add_pointer<CommandVT>::type CommandPT;
00300             typedef typename CommandVT::Signature ComSig;
00301             BOOST_STATIC_ASSERT( boost::function_traits<typename CommandVT::Signature>::arity == 3 );
00302 
00303             CommandPT c = this->getpointer(com);
00304             detail::LocalCommand<ComSig>* lc = dynamic_cast<detail::LocalCommand<ComSig>*>( c->getCommandImpl() );
00305             if ( !lc ) {
00306                 log(Error) << "Failed to addCommand: '"<< c->getName() <<"' is not a local command." <<endlog();
00307                 return false;
00308             }
00309             if ( this->addCommand( c ) == false )
00310                 return false;
00311             this->add( c->getName(), new detail::OperationFactoryPart3<DispatchInterface*, detail::DataSourceArgsCommand<ComSig> >(
00312                   detail::DataSourceArgsCommand<ComSig>(lc->getCommandFunction(),
00313                                                lc->getConditionFunction(),
00314                                                lc->getCommandProcessor(), lc->isInverted() ),
00315                   description, arg1, arg1_description,
00316                   arg2, arg2_description,
00317                   arg3, arg3_description) );
00318             return true;
00319         }
00320 
00339         template<class CommandT>
00340         bool addCommand( CommandT com, const char* description,
00341                          const char* arg1, const char* arg1_description,
00342                          const char* arg2, const char* arg2_description,
00343                          const char* arg3, const char* arg3_description,
00344                          const char* arg4, const char* arg4_description)
00345         {
00346             Logger::In in("CommandRepository");
00347             typedef typename boost::remove_pointer<CommandT>::type CommandVT;
00348             typedef typename boost::add_pointer<CommandVT>::type CommandPT;
00349             typedef typename CommandVT::Signature ComSig;
00350             BOOST_STATIC_ASSERT( boost::function_traits<typename CommandVT::Signature>::arity == 4 );
00351 
00352             CommandPT c = this->getpointer(com);
00353             detail::LocalCommand<ComSig>* lc = dynamic_cast<detail::LocalCommand<ComSig>*>( c->getCommandImpl() );
00354             if ( !lc ) {
00355                 log(Error) << "Failed to addCommand: '"<< c->getName() <<"' is not a local command." <<endlog();
00356                 return false;
00357             }
00358             if ( this->addCommand( c ) == false )
00359                 return false;
00360             this->add( c->getName(), new detail::OperationFactoryPart4<DispatchInterface*, detail::DataSourceArgsCommand<ComSig> >(
00361                   detail::DataSourceArgsCommand<ComSig>(lc->getCommandFunction(),
00362                                                lc->getConditionFunction(),
00363                                                lc->getCommandProcessor(), lc->isInverted() ),
00364                   description, arg1, arg1_description,
00365                   arg2, arg2_description,
00366                   arg3, arg3_description,
00367                   arg4, arg4_description) );
00368             return true;
00369         }
00370 
00379         DispatchInterface* getCommand( std::string name,
00380                                           const std::vector<DataSourceBase::shared_ptr>& args) const
00381         {
00382             return this->produce(name, args);
00383         }
00384 
00390         template<class CommandT,class CompT>
00391         bool addCommandDS( DataSource< boost::weak_ptr<CompT> >* wp, CommandT c, const char* description)
00392         {
00393             using namespace detail;
00394             typedef typename CommandT::Signature ComSig;
00395             if ( this->hasMember(c.getName() ) )
00396                 return false;
00397             typedef FunctorDS0<ComSig> CommandF;
00398             typedef detail::DataSourceArgsCommand<ComSig,
00399                                   CommandF> DSComm;
00400             this->add( c.getName(), new detail::OperationFactoryPart0<DispatchInterface*, DSComm>(
00401                         DSComm( CommandF(wp, c.getCommandFunction()),
00402                                 CommandF(wp, c.getConditionFunction()),
00403                                 c.getCommandProcessor(), c.isInverted() ),
00404                         description) );
00405             return true;
00406         }
00407 
00413         template<class CommandT, class CompT>
00414         bool addCommandDS( DataSource<boost::weak_ptr<CompT> >* wp, CommandT c, const char* description,
00415                          const char* arg1, const char* arg1_description)
00416         {
00417             using namespace detail;
00418             typedef typename CommandT::Signature ComSig;
00419             typedef FunctorDS1<ComSig> CommandF;
00420             typedef detail::DataSourceArgsCommand<ComSig,
00421                                   CommandF> DSComm;
00422             if ( this->hasMember(c.getName() ) )
00423                 return false;
00424             this->add( c.getName(), new detail::OperationFactoryPart1<DispatchInterface*, DSComm, typename DSComm::traits::arg2_type>(
00425                         DSComm( CommandF(wp, c.getCommandFunction()),
00426                                 CommandF(wp, c.getConditionFunction()),
00427                                 c.getCommandProcessor(), c.isInverted() ),
00428                         description, arg1, arg1_description) );
00429             return true;
00430         }
00431 
00440         ConditionInterface* getCondition( std::string name,
00441                                          const std::vector<DataSourceBase::shared_ptr>& args) const
00442         {
00443             DispatchInterface* di = this->produce(name, args);
00444             ConditionInterface* ret = di->createCondition();
00445             delete di;
00446             return ret;
00447         }
00448 
00457         CommandC create(std::string name) {
00458             return CommandC( this, name );
00459         }
00460 
00461 
00462     };
00463 
00464 }
00465 
00466 
00467 #endif
Generated on Thu Dec 23 13:22:36 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3