Orocos Real-Time Toolkit  2.5.0
OperationInterfaceI.cpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  OperationInterfaceI.cpp
00003 
00004                         OperationInterfaceI.cpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
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 // -*- C++ -*-
00040 //
00041 // $Id$
00042 
00043 // ****  Code generated by the The ACE ORB (TAO) IDL Compiler ****
00044 // TAO and the TAO IDL Compiler have been developed by:
00045 //       Center for Distributed Object Computing
00046 //       Washington University
00047 //       St. Louis, MO
00048 //       USA
00049 //       http://www.cs.wustl.edu/~schmidt/doc-center.html
00050 // and
00051 //       Distributed Object Computing Laboratory
00052 //       University of California at Irvine
00053 //       Irvine, CA
00054 //       USA
00055 //       http://doc.ece.uci.edu/
00056 // and
00057 //       Institute for Software Integrated Systems
00058 //       Vanderbilt University
00059 //       Nashville, TN
00060 //       USA
00061 //       http://www.isis.vanderbilt.edu/
00062 //
00063 // Information about TAO is available at:
00064 //     http://www.cs.wustl.edu/~schmidt/TAO.html
00065 
00066 // TAO_IDL - Generated from
00067 // ../../../ACE_wrappers/TAO/TAO_IDL/be/be_codegen.cpp:1196
00068 
00069 #include "CorbaLib.hpp"
00070 #include "CorbaTypeTransporter.hpp"
00071 #include "OperationInterfaceI.h"
00072 #include "AnyDataSource.hpp"
00073 #include "../../rtt-detail-fwd.hpp"
00074 #include "../../internal/OperationCallerC.hpp"
00075 #include "../../internal/SendHandleC.hpp"
00076 #include "../../Logger.hpp"
00077 
00078 using namespace RTT;
00079 using namespace RTT::detail;
00080 using namespace std;
00081 
00082 RTT_corba_CSendHandle_i::RTT_corba_CSendHandle_i (SendHandleC const& sh, OperationInterfacePart* ofp)
00083 : mhandle(sh), morig(sh), mofp(ofp)
00084 {
00085     // this will always be correct:
00086     for (unsigned int i = 1; i <= mofp->collectArity(); ++i) {
00087         const TypeInfo* ti = mofp->getCollectType(i); // retrieve 1..collectArity()
00088         assert(ti);
00089         cargs.push_back( ti->buildValue() );
00090         mhandle.arg( cargs.back() );
00091     }
00092     assert( mhandle.ready() );
00093 }
00094 
00095 RTT_corba_CSendHandle_i::~RTT_corba_CSendHandle_i (void)
00096 {
00097 }
00098 
00105 bool anysequence_to_sourcevector( CAnyArguments const& anys, vector<DataSourceBase::shared_ptr>& sources) {
00106     return false;
00107 }
00108 
00115 bool sourcevector_to_anysequence( vector<DataSourceBase::shared_ptr> const& sources, CAnyArguments & anys ) {
00116     bool valid = true;
00117     anys.length( sources.size() );
00118     for(unsigned int i = 0; i != sources.size(); ++i) {
00119         const TypeInfo* ti = sources[i]->getTypeInfo();
00120         CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00121         ctt->updateAny(sources[i], anys[i]);
00122     }
00123     return valid;
00124 }
00125 
00126 ::RTT::corba::CSendStatus RTT_corba_CSendHandle_i::collect (
00127     ::RTT::corba::CAnyArguments_out args)
00128 {
00129     SendStatus ss = mhandle.collect();
00130     args = new CAnyArguments();
00131     if (ss == SendSuccess) {
00132         sourcevector_to_anysequence( cargs, *args.ptr() );
00133     }
00134     return CSendStatus(static_cast<int>(ss) + 1);
00135 }
00136 
00137 ::RTT::corba::CSendStatus RTT_corba_CSendHandle_i::collectIfDone (
00138     ::RTT::corba::CAnyArguments_out args)
00139 {
00140     SendStatus ss = mhandle.collectIfDone();
00141     args = new CAnyArguments();
00142     if (ss == SendSuccess) {
00143         sourcevector_to_anysequence( cargs, *args.ptr() );
00144     }
00145     return CSendStatus(static_cast<int>(ss) + 1);
00146 }
00147 
00148 ::RTT::corba::CSendStatus RTT_corba_CSendHandle_i::checkStatus (
00149     void)
00150 {
00151     return CSendStatus( static_cast<int>(mhandle.collectIfDone()) + 1 );
00152 }
00153 
00154 ::CORBA::Any * RTT_corba_CSendHandle_i::ret (
00155     void)
00156 {
00157     SendStatus ss = mhandle.collectIfDone();
00158     // We just copy over the first collectable argument. In
00159     // case of a void operation, we will thus return the first
00160     // reference argument.
00161     if (ss == SendSuccess) {
00162         if ( cargs.size() > 0) {
00163             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (cargs[0]->getTypeInfo()->getProtocol(ORO_CORBA_PROTOCOL_ID));
00164             return ctt->createAny( cargs[0] );
00165         }
00166     }
00167     return new CORBA::Any();
00168 }
00169 
00170 void RTT_corba_CSendHandle_i::checkArguments (
00171     const ::RTT::corba::CAnyArguments & args)
00172 {
00173     try {
00174         SendHandleC shc(morig);
00175         for (unsigned int i = 0; i != mofp->collectArity(); ++i) {
00176             const TypeInfo* ti = mofp->getCollectType(i + 1);
00177             assert(ti);
00178             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (ti->getProtocol(ORO_CORBA_PROTOCOL_ID));
00179             shc.arg(ctt->createDataSource(&args[i]));
00180         }
00181         // otherwise, we would block !!!
00182         shc.setAutoCollect(false);
00183         shc.check();
00184     } catch (name_not_found_exception& nnf) {
00185         throw ::RTT::corba::CNoSuchNameException(nnf.name.c_str());
00186     } catch (wrong_number_of_args_exception& wna) {
00187         throw ::RTT::corba::CWrongNumbArgException(wna.wanted, wna.received);
00188     } catch (wrong_types_of_args_exception& wta) {
00189         throw ::RTT::corba::CWrongTypeArgException(wta.whicharg, wta.expected_.c_str(), wta.received_.c_str());
00190     }
00191 }
00192 
00193 void RTT_corba_CSendHandle_i::dispose (
00194     void)
00195 {
00196     PortableServer::POA_var mPOA = _default_POA();
00197     PortableServer::ObjectId_var oid = mPOA->servant_to_id(this);
00198     mPOA->deactivate_object( oid.in() );
00199     return;
00200 }
00201 
00202 // Implementation skeleton constructor
00203 RTT_corba_COperationInterface_i::RTT_corba_COperationInterface_i (OperationInterface* gmf, PortableServer::POA_ptr the_poa)
00204     :mfact(gmf), mpoa( PortableServer::POA::_duplicate(the_poa))
00205 {
00206 }
00207 
00208 PortableServer::POA_ptr RTT_corba_COperationInterface_i::_default_POA()
00209 {
00210     return PortableServer::POA::_duplicate(mpoa);
00211 }
00212 
00213 
00214 // Implementation skeleton destructor
00215 RTT_corba_COperationInterface_i::~RTT_corba_COperationInterface_i (void)
00216 {
00217 }
00218 
00219 ::RTT::corba::COperationInterface::COperationList * RTT_corba_COperationInterface_i::getOperations (
00220     void)
00221 {
00222     RTT::corba::COperationInterface::COperationList_var rlist = new RTT::corba::COperationInterface::COperationList();
00223 
00224     vector<string> flist = mfact->getNames();
00225     rlist->length( flist.size() );
00226     size_t drops=0;
00227     for (size_t i=0; i != flist.size(); ++i)
00228         if ( !mfact->isSynchronous(flist[i]) ) {
00229             rlist[i - drops] = CORBA::string_dup( flist[i].c_str() );
00230         } else {
00231             ++drops;
00232         }
00233     rlist->length( flist.size() - drops); // we don't show the synchronous operations.
00234     return rlist._retn();
00235 }
00236 
00237 ::RTT::corba::CDescriptions * RTT_corba_COperationInterface_i::getArguments (
00238     const char * operation)
00239 {
00240     CDescriptions_var ret = new CDescriptions();
00241     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)))
00242         throw ::RTT::corba::CNoSuchNameException( operation );
00243     // operation found, convert args:
00244     OperationInterface::Descriptions args = mfact->getArgumentList( string(operation) );
00245     ret->length( args.size() );
00246     for (size_t i =0; i != args.size(); ++i) {
00247         ret[i].name = CORBA::string_dup( args[i].name.c_str() );
00248         ret[i].description = CORBA::string_dup( args[i].description.c_str() );
00249         ret[i].type = CORBA::string_dup( args[i].type.c_str() );
00250     }
00251     return ret._retn();
00252 }
00253 
00254 char * RTT_corba_COperationInterface_i::getResultType (
00255     const char * operation)
00256 {
00257     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00258         throw ::RTT::corba::CNoSuchNameException( operation );
00259     return CORBA::string_dup( mfact->getResultType( string(operation) ).c_str() );
00260 }
00261 
00262 char* RTT_corba_COperationInterface_i::getArgumentType(
00263         const char* operation,
00264         CORBA::UShort nbr)
00265 {
00266     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00267         throw ::RTT::corba::CNoSuchNameException( operation );
00268     if ( nbr > mfact->getPart(operation)->arity() )
00269         throw ::RTT::corba::CWrongArgumentException( nbr, mfact->getPart(operation)->arity() );
00270     return CORBA::string_dup( mfact->getPart( operation )->getArgumentType(nbr)->getTypeName().c_str() );
00271 }
00272 
00273 char* RTT_corba_COperationInterface_i::getCollectType(
00274         const char* operation,
00275         CORBA::UShort nbr)
00276 {
00277     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00278         throw ::RTT::corba::CNoSuchNameException( operation );
00279     if ( nbr > mfact->getPart(operation)->collectArity() )
00280         throw ::RTT::corba::CWrongArgumentException( nbr, mfact->getPart(operation)->collectArity() );
00281     return CORBA::string_dup( mfact->getPart( operation )->getCollectType(nbr)->getTypeName().c_str() );
00282 
00283 }
00284 
00285 ::CORBA::UShort RTT_corba_COperationInterface_i::getArity (
00286     const char * operation)
00287 {
00288     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00289         throw ::RTT::corba::CNoSuchNameException( operation );
00290     return mfact->getPart(operation)->arity();
00291 }
00292 
00293 ::CORBA::UShort RTT_corba_COperationInterface_i::getCollectArity (
00294     const char * operation)
00295 {
00296     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00297         throw ::RTT::corba::CNoSuchNameException( operation );
00298     return mfact->getPart(operation)->collectArity();
00299 }
00300 
00301 char * RTT_corba_COperationInterface_i::getDescription (
00302     const char * operation)
00303 {
00304     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00305         throw ::RTT::corba::CNoSuchNameException( operation );
00306     return CORBA::string_dup( mfact->getDescription( string(operation) ).c_str() );
00307 }
00308 
00309 void RTT_corba_COperationInterface_i::checkOperation (
00310     const char * operation,
00311     const ::RTT::corba::CAnyArguments & args)
00312 {
00313     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00314         throw ::RTT::corba::CNoSuchNameException( operation );
00315     try {
00316         OperationInterfacePart* mofp = mfact->getPart(operation);
00317         OperationCallerC mc(mofp, operation, 0);
00318         for (unsigned int i = 0; i < mofp->arity() && i < args.length(); ++i) {
00319             const TypeInfo* ti = mofp->getArgumentType(i+1);
00320             assert(ti);
00321             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (ti->getProtocol(ORO_CORBA_PROTOCOL_ID));
00322             if (ctt) {
00323         DataSourceBase::shared_ptr ds = ctt->createDataSource(&args[i]);
00324         if (ds)
00325             mc.arg(ds);
00326         else {
00327             log(Error) << "Registered transport for type "<< ti->getTypeName()
00328                     << " could not create data source from Any (argument "<< i+1
00329                     <<"): calling operation '"<< operation <<"' will fail." <<endlog();
00330         }
00331             } else {
00332         throw wrong_types_of_args_exception(i+1,"type known to CORBA", ti->getTypeName());
00333             }
00334         }
00335         mc.check();
00336     } catch (no_asynchronous_operation_exception& ) {
00337         throw ::RTT::corba::CNoSuchNameException(operation);
00338     } catch (name_not_found_exception& nnf) {
00339         throw ::RTT::corba::CNoSuchNameException(nnf.name.c_str());
00340     } catch (wrong_number_of_args_exception& wna) {
00341         throw ::RTT::corba::CWrongNumbArgException(wna.wanted, wna.received);
00342     } catch (wrong_types_of_args_exception& wta) {
00343         throw ::RTT::corba::CWrongTypeArgException(wta.whicharg, wta.expected_.c_str(), wta.received_.c_str());
00344     }
00345 }
00346 
00347 ::CORBA::Any * RTT_corba_COperationInterface_i::callOperation (
00348     const char * operation,
00349     ::RTT::corba::CAnyArguments & args)
00350 {
00351     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00352         throw ::RTT::corba::CNoSuchNameException( operation );
00353     // convert Corba args to C++ args.
00354     try {
00355         OperationCallerC orig(mfact->getPart(operation), operation, 0);
00356         vector<DataSourceBase::shared_ptr> results;
00357         for (size_t i =0; i != args.length(); ++i) {
00358             const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00359             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00360             // we need to store the results for returning them to caller (args is inout!) after the call()
00361             results.push_back( ctt->createDataSource( &args[i] ) );
00362             orig.arg( results[i] );
00363         }
00364         if ( orig.ready() ) {
00365             DataSourceBase::shared_ptr ds = orig.getCallDataSource();
00366             CORBA::Any* retany;
00367 
00368             // Try to get the return result :
00369             const TypeInfo* ti = ds->getTypeInfo();
00370             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00371             if ( !ctt ) {
00372                 log(Warning) << "Could not return results of call to " << operation << ": unknown return type by CORBA transport."<<endlog();
00373                 ds->evaluate(); // equivalent to orig.call()
00374                 retany = new CORBA::Any();
00375             } else {
00376                 retany =  ctt->createAny( ds ); // call evaluate internally
00377             }
00378 
00379             // Return results into args:
00380             for (size_t i =0; i != args.length(); ++i) {
00381                 const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00382                 CorbaTypeTransporter* ctta = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00383                 ctta->updateAny(results[i], args[i]);
00384             }
00385             return retany;
00386         } else {
00387             orig.check(); // will throw
00388         }
00389     } catch (no_asynchronous_operation_exception& ) {
00390         throw ::RTT::corba::CNoSuchNameException( operation );
00391     } catch ( name_not_found_exception& ) {
00392         throw ::RTT::corba::CNoSuchNameException( operation );
00393     } catch ( wrong_number_of_args_exception& wna ) {
00394         throw ::RTT::corba::CWrongNumbArgException( wna.wanted, wna.received );
00395     } catch (wrong_types_of_args_exception& wta ) {
00396         throw ::RTT::corba::CWrongTypeArgException( wta.whicharg, wta.expected_.c_str(), wta.received_.c_str() );
00397     }
00398     return new ::CORBA::Any();
00399 }
00400 
00401 ::RTT::corba::CSendHandle_ptr RTT_corba_COperationInterface_i::sendOperation (
00402     const char * operation,
00403     const ::RTT::corba::CAnyArguments & args)
00404 {
00405     // This implementation is 90% identical to callOperation above, only deviating in the orig.ready() part.
00406     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00407         throw ::RTT::corba::CNoSuchNameException( operation );
00408     // convert Corba args to C++ args.
00409     try {
00410         OperationCallerC orig(mfact->getPart(operation), operation, 0);
00411         for (size_t i =0; i != args.length(); ++i) {
00412             const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00413             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00414             orig.arg( ctt->createDataSource( &args[i] ));
00415         }
00416         if ( orig.ready() ) {
00417             SendHandleC resulthandle = orig.send();
00418             // we may not destroy the SendHandle, before the operation completes:
00419             resulthandle.setAutoCollect(true);
00420             // our resulthandle copy makes sure that the resulthandle can return.
00421             RTT_corba_CSendHandle_i* ret_i = new RTT_corba_CSendHandle_i( resulthandle, mfact->getPart(operation) );
00422             CSendHandle_var ret = ret_i->_this();
00423             ret_i->_remove_ref(); // if POA drops this, it gets cleaned up.
00424             return ret._retn();
00425         } else {
00426             orig.check(); // will throw
00427         }
00428     } catch (no_asynchronous_operation_exception& ) {
00429         throw ::RTT::corba::CNoSuchNameException( operation );
00430     } catch ( name_not_found_exception& ) {
00431         throw ::RTT::corba::CNoSuchNameException( operation );
00432     } catch ( wrong_number_of_args_exception& wna ) {
00433         throw ::RTT::corba::CWrongNumbArgException( wna.wanted, wna.received );
00434     } catch (wrong_types_of_args_exception& wta ) {
00435         throw ::RTT::corba::CWrongTypeArgException( wta.whicharg, wta.expected_.c_str(), wta.received_.c_str() );
00436     }
00437     return CSendHandle::_nil();
00438 }