Orocos Real-Time Toolkit
2.6.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 DataSourceProxy.hpp 00003 00004 DataSourceProxy.hpp - 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 #ifndef ORO_CORBA_DATASOURCE_PROXY_HPP 00040 #define ORO_CORBA_DATASOURCE_PROXY_HPP 00041 00042 #include "../../internal/DataSource.hpp" 00043 #include "../../Logger.hpp" 00044 #include "../../base/ActionInterface.hpp" 00045 #include "CorbaConversion.hpp" 00046 #include "CorbaTypeTransporter.hpp" 00047 #include "CorbaLib.hpp" 00048 #include <cassert> 00049 00050 namespace RTT 00051 { 00052 namespace corba 00053 { 00059 struct NonExistingDataSource 00060 { 00061 }; 00065 template<class T> 00066 class DataSourceProxy 00067 : public internal::DataSource<T> 00068 { 00069 corba::CService_var mserv; 00070 const std::string mname; 00071 bool misproperty; 00072 mutable typename internal::DataSource<T>::value_t last_value; 00073 CorbaTypeTransporter* ctp; 00074 00075 public: 00085 DataSourceProxy( corba::CService_ptr s, const std::string& name, bool isproperty ) 00086 : mserv( corba::CService::_duplicate( s ) ), mname(name), misproperty(isproperty) 00087 { 00088 assert( !CORBA::is_nil(s) ); 00089 types::TypeTransporter* tp = this->getTypeInfo()->getProtocol(ORO_CORBA_PROTOCOL_ID); 00090 ctp = dynamic_cast<corba::CorbaTypeTransporter*>(tp); 00091 assert( ctp ); // only call this from CorbaTempateTypeInfo. 00092 if ( misproperty && ! mserv->hasProperty( name.c_str())) 00093 throw NonExistingDataSource(); 00094 if ( !misproperty && ! mserv->hasAttribute( name.c_str())) 00095 throw NonExistingDataSource(); 00096 } 00097 00098 typename internal::DataSource<T>::result_t value() const { 00099 return last_value; 00100 } 00101 00102 typename internal::AssignableDataSource<T>::const_reference_t rvalue() const { 00103 return last_value; 00104 } 00105 00106 virtual typename internal::DataSource<T>::result_t get() const { 00107 CORBA::Any_var res; 00108 if ( misproperty ) { 00109 res = mserv->getProperty( mname.c_str() ); 00110 } else { 00111 res = mserv->getAttribute( mname.c_str() ); 00112 } 00113 internal::ReferenceDataSource<T> rds(last_value); 00114 rds.ref(); 00115 if ( ctp->updateFromAny(&res.in(),&rds ) == false) 00116 Logger::log() <<Logger::Error << "Could not update DataSourceProxy from remote value!"<<Logger::endl; 00117 return last_value; 00118 } 00119 00120 virtual internal::DataSource<T>* clone() const { 00121 return new DataSourceProxy<T>( corba::CService::_duplicate( mserv.in() ), mname, misproperty ); 00122 } 00123 00124 virtual internal::DataSource<T>* copy( std::map<const base::DataSourceBase*, base::DataSourceBase*>& alreadyCloned ) const { 00125 alreadyCloned[this] = const_cast<DataSourceProxy<T>*>(this); 00126 return const_cast<DataSourceProxy<T>*>(this); 00127 } 00128 00129 virtual std::string getType() const { 00130 // both should be equivalent, but we display the local type. 00131 return internal::DataSource<T>::GetType(); 00132 //return std::string( mserv->getType() ); 00133 } 00134 00135 }; 00136 00140 template<class T> 00141 class ValueDataSourceProxy 00142 : public internal::AssignableDataSource<T> 00143 { 00144 typedef typename internal::AssignableDataSource<T>::value_t value_t; 00145 corba::CService_var mserv; 00146 const std::string mname; 00147 bool misproperty; 00148 typename internal::AssignableDataSource<value_t>::shared_ptr storage; 00149 CorbaTypeTransporter* ctp; 00150 //mutable typename internal::DataSource<T>::value_t last_value; 00151 00152 public: 00153 ValueDataSourceProxy( corba::CService_ptr serv, const std::string& name, bool isproperty) 00154 : mserv( corba::CService::_duplicate(serv) ), mname(name), misproperty(isproperty) 00155 { 00156 storage = new internal::ValueDataSource<value_t>(); 00157 assert( serv ); 00158 types::TypeTransporter* tp = this->getTypeInfo()->getProtocol(ORO_CORBA_PROTOCOL_ID); 00159 ctp = dynamic_cast<corba::CorbaTypeTransporter*>(tp); 00160 assert(ctp); 00161 if ( misproperty && !mserv->hasProperty( name.c_str()) ) 00162 throw NonExistingDataSource(); 00163 if ( !misproperty && ( !mserv->hasAttribute( name.c_str()) || !mserv->isAttributeAssignable( name.c_str()) )) 00164 throw NonExistingDataSource(); 00165 this->get(); // initialize such that value()/rvalue() return a sane value ! 00166 } 00167 00168 typename internal::DataSource<T>::result_t value() const { 00169 return storage->rvalue(); 00170 } 00171 00172 typename internal::AssignableDataSource<T>::const_reference_t rvalue() const { 00173 return storage->rvalue(); 00174 } 00175 00176 00177 virtual typename internal::DataSource<T>::result_t get() const { 00178 CORBA::Any_var res; 00179 if ( misproperty ) { 00180 res = mserv->getProperty( mname.c_str() ); 00181 } else { 00182 res = mserv->getAttribute( mname.c_str() ); 00183 } 00184 internal::ReferenceDataSource<T> rds( storage->set() ); 00185 rds.ref(); 00186 if ( ctp->updateFromAny(&res.in(), &rds ) == false) 00187 Logger::log() <<Logger::Error << "Could not update ValueDataSourceProxy from remote value!"<<Logger::endl; 00188 return storage->rvalue(); 00189 } 00190 00191 virtual void set( typename internal::AssignableDataSource<T>::param_t t ) { 00192 internal::ValueDataSource<T> vds(t); 00193 vds.ref(); 00194 CORBA::Any_var toset = ctp->createAny(&vds); 00195 if ( misproperty ) { 00196 mserv->setProperty( mname.c_str(), toset.in() ); 00197 } else { 00198 mserv->setAttribute( mname.c_str(), toset.in() ); 00199 } 00200 storage->set( t ); 00201 } 00202 00203 virtual typename internal::AssignableDataSource<T>::reference_t set() { 00204 this->get(); 00205 return storage->set(); 00206 } 00207 00208 virtual void updated() 00209 { 00210 this->set( storage->value() ); 00211 } 00212 00213 virtual internal::AssignableDataSource<T>* clone() const { 00214 return new ValueDataSourceProxy<T>( corba::CService::_duplicate( mserv.in() ), mname, misproperty ); 00215 } 00216 00217 virtual internal::AssignableDataSource<T>* copy( std::map<const base::DataSourceBase*, base::DataSourceBase*>& alreadyCloned ) const { 00218 alreadyCloned[this] = const_cast<ValueDataSourceProxy<T>*>(this); 00219 return const_cast<ValueDataSourceProxy<T>*>(this); 00220 } 00221 }; 00222 00223 } 00224 } 00225 00226 #endif