Orocos Real-Time Toolkit  2.6.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     try {
00130         SendStatus ss = mhandle.collect();
00131         args = new CAnyArguments();
00132         if (ss == SendSuccess) {
00133            sourcevector_to_anysequence( cargs, *args.ptr() );
00134         }
00135         return CSendStatus(static_cast<int>(ss) + 1);
00136     } catch(std::runtime_error& e) {
00137         throw ::RTT::corba::CCallError(e.what());
00138     }
00139 }
00140 
00141 ::RTT::corba::CSendStatus RTT_corba_CSendHandle_i::collectIfDone (
00142     ::RTT::corba::CAnyArguments_out args)
00143 {
00144     try {
00145         SendStatus ss = mhandle.collectIfDone();
00146         args = new CAnyArguments();
00147         if (ss == SendSuccess) {
00148             sourcevector_to_anysequence( cargs, *args.ptr() );
00149         }
00150         return CSendStatus(static_cast<int>(ss) + 1);
00151     } catch(std::runtime_error& e) {
00152         throw ::RTT::corba::CCallError(e.what());
00153     }
00154 }
00155 
00156 ::RTT::corba::CSendStatus RTT_corba_CSendHandle_i::checkStatus (
00157     void)
00158 {
00159     return CSendStatus( static_cast<int>(mhandle.collectIfDone()) + 1 );
00160 }
00161 
00162 ::CORBA::Any * RTT_corba_CSendHandle_i::ret (
00163     void)
00164 {
00165     try {
00166         SendStatus ss = mhandle.collectIfDone();
00167         // We just copy over the first collectable argument. In
00168         // case of a void operation, we will thus return the first
00169         // reference argument.
00170         if (ss == SendSuccess) {
00171             if ( cargs.size() > 0) {
00172                 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (cargs[0]->getTypeInfo()->getProtocol(ORO_CORBA_PROTOCOL_ID));
00173                 return ctt->createAny( cargs[0] );
00174             }
00175         }
00176         return new CORBA::Any();
00177     } catch(std::runtime_error& e) {
00178         throw ::RTT::corba::CCallError(e.what());
00179     }
00180 }
00181 
00182 void RTT_corba_CSendHandle_i::checkArguments (
00183     const ::RTT::corba::CAnyArguments & args)
00184 {
00185     try {
00186         SendHandleC shc(morig);
00187         for (unsigned int i = 0; i != mofp->collectArity(); ++i) {
00188             const TypeInfo* ti = mofp->getCollectType(i + 1);
00189             assert(ti);
00190             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (ti->getProtocol(ORO_CORBA_PROTOCOL_ID));
00191             shc.arg(ctt->createDataSource(&args[i]));
00192         }
00193         // otherwise, we would block !!!
00194         shc.setAutoCollect(false);
00195         shc.check();
00196     } catch (name_not_found_exception& nnf) {
00197         throw ::RTT::corba::CNoSuchNameException(nnf.name.c_str());
00198     } catch (wrong_number_of_args_exception& wna) {
00199         throw ::RTT::corba::CWrongNumbArgException(wna.wanted, wna.received);
00200     } catch (wrong_types_of_args_exception& wta) {
00201         throw ::RTT::corba::CWrongTypeArgException(wta.whicharg, wta.expected_.c_str(), wta.received_.c_str());
00202     }
00203 }
00204 
00205 void RTT_corba_CSendHandle_i::dispose (
00206     void)
00207 {
00208     PortableServer::POA_var mPOA = _default_POA();
00209     PortableServer::ObjectId_var oid = mPOA->servant_to_id(this);
00210     mPOA->deactivate_object( oid.in() );
00211     return;
00212 }
00213 
00214 // Implementation skeleton constructor
00215 RTT_corba_COperationInterface_i::RTT_corba_COperationInterface_i (OperationInterface* gmf, PortableServer::POA_ptr the_poa)
00216     :mfact(gmf), mpoa( PortableServer::POA::_duplicate(the_poa))
00217 {
00218 }
00219 
00220 PortableServer::POA_ptr RTT_corba_COperationInterface_i::_default_POA()
00221 {
00222     return PortableServer::POA::_duplicate(mpoa);
00223 }
00224 
00225 
00226 // Implementation skeleton destructor
00227 RTT_corba_COperationInterface_i::~RTT_corba_COperationInterface_i (void)
00228 {
00229 }
00230 
00231 ::RTT::corba::COperationInterface::COperationList * RTT_corba_COperationInterface_i::getOperations (
00232     void)
00233 {
00234     RTT::corba::COperationInterface::COperationList_var rlist = new RTT::corba::COperationInterface::COperationList();
00235 
00236     vector<string> flist = mfact->getNames();
00237     rlist->length( flist.size() );
00238     size_t drops=0;
00239     for (size_t i=0; i != flist.size(); ++i)
00240         if ( !mfact->isSynchronous(flist[i]) ) {
00241             rlist[i - drops] = CORBA::string_dup( flist[i].c_str() );
00242         } else {
00243             ++drops;
00244         }
00245     rlist->length( flist.size() - drops); // we don't show the synchronous operations.
00246     return rlist._retn();
00247 }
00248 
00249 ::RTT::corba::CDescriptions * RTT_corba_COperationInterface_i::getArguments (
00250     const char * operation)
00251 {
00252     CDescriptions_var ret = new CDescriptions();
00253     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)))
00254         throw ::RTT::corba::CNoSuchNameException( operation );
00255     // operation found, convert args:
00256     OperationInterface::Descriptions args = mfact->getArgumentList( string(operation) );
00257     ret->length( args.size() );
00258     for (size_t i =0; i != args.size(); ++i) {
00259         ret[i].name = CORBA::string_dup( args[i].name.c_str() );
00260         ret[i].description = CORBA::string_dup( args[i].description.c_str() );
00261         ret[i].type = CORBA::string_dup( args[i].type.c_str() );
00262     }
00263     return ret._retn();
00264 }
00265 
00266 char * RTT_corba_COperationInterface_i::getResultType (
00267     const char * operation)
00268 {
00269     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00270         throw ::RTT::corba::CNoSuchNameException( operation );
00271     return CORBA::string_dup( mfact->getResultType( string(operation) ).c_str() );
00272 }
00273 
00274 char* RTT_corba_COperationInterface_i::getArgumentType(
00275         const char* operation,
00276         CORBA::UShort nbr)
00277 {
00278     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00279         throw ::RTT::corba::CNoSuchNameException( operation );
00280     if ( nbr > mfact->getPart(operation)->arity() )
00281         throw ::RTT::corba::CWrongArgumentException( nbr, mfact->getPart(operation)->arity() );
00282     return CORBA::string_dup( mfact->getPart( operation )->getArgumentType(nbr)->getTypeName().c_str() );
00283 }
00284 
00285 char* RTT_corba_COperationInterface_i::getCollectType(
00286         const char* operation,
00287         CORBA::UShort nbr)
00288 {
00289     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00290         throw ::RTT::corba::CNoSuchNameException( operation );
00291     if ( nbr > mfact->getPart(operation)->collectArity() )
00292         throw ::RTT::corba::CWrongArgumentException( nbr, mfact->getPart(operation)->collectArity() );
00293     return CORBA::string_dup( mfact->getPart( operation )->getCollectType(nbr)->getTypeName().c_str() );
00294 
00295 }
00296 
00297 ::CORBA::UShort RTT_corba_COperationInterface_i::getArity (
00298     const char * operation)
00299 {
00300     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00301         throw ::RTT::corba::CNoSuchNameException( operation );
00302     return mfact->getPart(operation)->arity();
00303 }
00304 
00305 ::CORBA::UShort RTT_corba_COperationInterface_i::getCollectArity (
00306     const char * operation)
00307 {
00308     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00309         throw ::RTT::corba::CNoSuchNameException( operation );
00310     return mfact->getPart(operation)->collectArity();
00311 }
00312 
00313 char * RTT_corba_COperationInterface_i::getDescription (
00314     const char * operation)
00315 {
00316     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00317         throw ::RTT::corba::CNoSuchNameException( operation );
00318     return CORBA::string_dup( mfact->getDescription( string(operation) ).c_str() );
00319 }
00320 
00321 void RTT_corba_COperationInterface_i::checkOperation (
00322     const char * operation,
00323     const ::RTT::corba::CAnyArguments & args)
00324 {
00325     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00326         throw ::RTT::corba::CNoSuchNameException( operation );
00327     try {
00328         OperationInterfacePart* mofp = mfact->getPart(operation);
00329         OperationCallerC mc(mofp, operation, 0);
00330         for (unsigned int i = 0; i < mofp->arity() && i < args.length(); ++i) {
00331             const TypeInfo* ti = mofp->getArgumentType(i+1);
00332             assert(ti);
00333             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> (ti->getProtocol(ORO_CORBA_PROTOCOL_ID));
00334             if (ctt) {
00335         DataSourceBase::shared_ptr ds = ctt->createDataSource(&args[i]);
00336         if (ds)
00337             mc.arg(ds);
00338         else {
00339             log(Error) << "Registered transport for type "<< ti->getTypeName()
00340                     << " could not create data source from Any (argument "<< i+1
00341                     <<"): calling operation '"<< operation <<"' will fail." <<endlog();
00342         }
00343             } else {
00344         throw wrong_types_of_args_exception(i+1,"type known to CORBA", ti->getTypeName());
00345             }
00346         }
00347         mc.check();
00348     } catch (no_asynchronous_operation_exception& ) {
00349         throw ::RTT::corba::CNoSuchNameException(operation);
00350     } catch (name_not_found_exception& nnf) {
00351         throw ::RTT::corba::CNoSuchNameException(nnf.name.c_str());
00352     } catch (wrong_number_of_args_exception& wna) {
00353         throw ::RTT::corba::CWrongNumbArgException(wna.wanted, wna.received);
00354     } catch (wrong_types_of_args_exception& wta) {
00355         throw ::RTT::corba::CWrongTypeArgException(wta.whicharg, wta.expected_.c_str(), wta.received_.c_str());
00356     }
00357 }
00358 
00359 ::CORBA::Any * RTT_corba_COperationInterface_i::callOperation (
00360     const char * operation,
00361     ::RTT::corba::CAnyArguments & args)
00362 {
00363     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00364         throw ::RTT::corba::CNoSuchNameException( operation );
00365     // convert Corba args to C++ args.
00366     try {
00367         OperationCallerC orig(mfact->getPart(operation), operation, 0);
00368         vector<DataSourceBase::shared_ptr> results;
00369         for (size_t i =0; i != args.length(); ++i) {
00370             const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00371             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00372             // we need to store the results for returning them to caller (args is inout!) after the call()
00373             results.push_back( ctt->createDataSource( &args[i] ) );
00374             orig.arg( results[i] );
00375         }
00376         if ( orig.ready() ) {
00377             DataSourceBase::shared_ptr ds = orig.getCallDataSource();
00378             CORBA::Any* retany;
00379 
00380             // Try to get the return result :
00381             const TypeInfo* ti = ds->getTypeInfo();
00382             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00383             if ( !ctt ) {
00384                 log(Warning) << "Could not return results of call to " << operation << ": unknown return type by CORBA transport."<<endlog();
00385                 ds->evaluate(); // equivalent to orig.call()
00386                 retany = new CORBA::Any();
00387             } else {
00388                 retany =  ctt->createAny( ds ); // call evaluate internally
00389             }
00390 
00391             // Return results into args:
00392             for (size_t i =0; i != args.length(); ++i) {
00393                 const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00394                 CorbaTypeTransporter* ctta = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00395                 ctta->updateAny(results[i], args[i]);
00396             }
00397             return retany;
00398         } else {
00399             orig.check(); // will throw
00400         }
00401     } catch (no_asynchronous_operation_exception& ) {
00402         throw ::RTT::corba::CNoSuchNameException( operation );
00403     } catch ( name_not_found_exception& ) {
00404         throw ::RTT::corba::CNoSuchNameException( operation );
00405     } catch ( wrong_number_of_args_exception& wna ) {
00406         throw ::RTT::corba::CWrongNumbArgException( wna.wanted, wna.received );
00407     } catch (wrong_types_of_args_exception& wta ) {
00408         throw ::RTT::corba::CWrongTypeArgException( wta.whicharg, wta.expected_.c_str(), wta.received_.c_str() );
00409     } catch (std::runtime_error& e){
00410         throw ::RTT::corba::CCallError(e.what());
00411     }
00412     return new ::CORBA::Any();
00413 }
00414 
00415 ::RTT::corba::CSendHandle_ptr RTT_corba_COperationInterface_i::sendOperation (
00416     const char * operation,
00417     const ::RTT::corba::CAnyArguments & args)
00418 {
00419     // This implementation is 90% identical to callOperation above, only deviating in the orig.ready() part.
00420     if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) )
00421         throw ::RTT::corba::CNoSuchNameException( operation );
00422     // convert Corba args to C++ args.
00423     try {
00424         OperationCallerC orig(mfact->getPart(operation), operation, 0);
00425         for (size_t i =0; i != args.length(); ++i) {
00426             const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1);
00427             CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00428             orig.arg( ctt->createDataSource( &args[i] ));
00429         }
00430         if ( orig.ready() ) {
00431             SendHandleC resulthandle = orig.send();
00432             // we may not destroy the SendHandle, before the operation completes:
00433             resulthandle.setAutoCollect(true);
00434             // our resulthandle copy makes sure that the resulthandle can return.
00435             RTT_corba_CSendHandle_i* ret_i = new RTT_corba_CSendHandle_i( resulthandle, mfact->getPart(operation) );
00436             CSendHandle_var ret = ret_i->_this();
00437             ret_i->_remove_ref(); // if POA drops this, it gets cleaned up.
00438             return ret._retn();
00439         } else {
00440             orig.check(); // will throw
00441         }
00442     } catch (no_asynchronous_operation_exception& ) {
00443         throw ::RTT::corba::CNoSuchNameException( operation );
00444     } catch ( name_not_found_exception& ) {
00445         throw ::RTT::corba::CNoSuchNameException( operation );
00446     } catch ( wrong_number_of_args_exception& wna ) {
00447         throw ::RTT::corba::CWrongNumbArgException( wna.wanted, wna.received );
00448     } catch (wrong_types_of_args_exception& wta ) {
00449         throw ::RTT::corba::CWrongTypeArgException( wta.whicharg, wta.expected_.c_str(), wta.received_.c_str() );
00450     }
00451     return CSendHandle::_nil();
00452 }