Orocos Real-Time Toolkit  2.6.0
Property.hpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 19 14:11:19 CET 2004  Property.hpp
00003 
00004                         Property.hpp -  description
00005                            -------------------
00006     begin                : Mon January 19 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.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 #ifndef ORO_PROPERTY_HPP
00039 #define ORO_PROPERTY_HPP
00040 
00041 #include "rtt-config.h"
00042 #include "base/PropertyBase.hpp"
00043 #include "PropertyBag.hpp"
00044 #include "internal/DataSources.hpp"
00045 #include <boost/type_traits/remove_const.hpp>
00046 #include <boost/call_traits.hpp>
00047 #include "Logger.hpp"
00048 
00049 #include <string>
00050 #include <ostream>
00051 
00052 #ifdef ORO_PRAGMA_INTERFACE
00053 #pragma interface
00054 #endif
00055 
00056 namespace RTT
00057 {
00075     template<typename T>
00076     class Property
00077         : public base::PropertyBase
00078     {
00079     public:
00085         typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type value_t;
00086         typedef typename boost::call_traits<value_t>::param_type param_t;
00087         typedef typename boost::call_traits<value_t>::reference reference_t;
00088         typedef typename boost::call_traits<value_t>::const_reference const_reference_t;
00089         typedef value_t DataSourceType;
00090 
00095         Property()
00096         {}
00097 
00104         explicit Property(const std::string& name)
00105             : base::PropertyBase(name,""), _value( new internal::ValueDataSource<value_t>() )
00106         {
00107         }
00108 
00117         Property(const std::string& name, const std::string& description, param_t value = value_t() )
00118             : base::PropertyBase(name, description), _value( new internal::ValueDataSource<value_t>( value ) )
00119         {
00120         }
00121 
00127         Property( const Property<T>& orig)
00128             : base::PropertyBase(orig.getName(), orig.getDescription()),
00129               _value( orig._value ? orig._value->clone() : 0 )
00130         {
00131             // need to do this on the clone() in order to have access to set()/rvalue() of the data source.
00132             if (_value)
00133                 _value->evaluate();
00134         }
00135 
00142         Property( base::PropertyBase* source)
00143             : base::PropertyBase(source ? source->getName() : "", source ? source->getDescription() : ""),
00144               _value( source ? internal::AssignableDataSource<DataSourceType>::narrow(source->getDataSource().get() ) : 0 )
00145         {
00146             if ( source && ! _value ) {
00147                 log(Error) <<"Can not initialize Property from "<<source->getName() <<": ";
00148                 if ( source->getDataSource() )
00149                     log() << "incompatible type ( destination type: "<< getType() << ", source type: "<< source->getDataSource()->getTypeName() << ")."<<endlog();
00150                 else
00151                     log() << "source Property was not ready."<<endlog();
00152             }
00153         }
00154 
00164         Property(const std::string& name, const std::string& description,
00165                  typename internal::AssignableDataSource<DataSourceType>::shared_ptr datasource )
00166             : base::PropertyBase(name, description), _value( datasource )
00167         {
00168             // need to do this on the datasource in order to have access to set()/rvalue() of the data source.
00169             if (_value)
00170                 _value->evaluate();
00171         }
00172 
00178         Property<T>& operator=( param_t value )
00179         {
00180             _value->set( value );
00181             return *this;
00182         }
00183 
00188         Property<T>& operator=( base::PropertyBase* source )
00189         {
00190             if ( this == source )
00191                 return *this;
00192 
00193             if ( source ) {
00194                 this->setName( source->getName() );
00195                 this->setDescription( source->getDescription() );
00196                 typename internal::AssignableDataSource<DataSourceType>::shared_ptr vptr
00197                     = internal::AssignableDataSource<DataSourceType>::narrow(source->getDataSource().get() );
00198                 if (vptr) {
00199                     _value = vptr;
00200                     return *this;
00201                 }
00202             }
00203             // wrong assignment: mark not ready.
00204             this->setName( "" );
00205             this->setDescription( "" );
00206             _value = 0;
00207             return *this;
00208         }
00209 
00214         Property<T>& operator<<=(Property<T> &p)
00215         {
00216             this->update( p );
00217             return *this;
00218         }
00219 
00225         Property<T>& doc(const std::string& descr) {
00226             setDescription(descr);
00227             return *this;
00228         }
00229 
00234         operator value_t() const
00235         {
00236             return _value->get();
00237         }
00238 
00243         DataSourceType get() const
00244         {
00245             return _value->get();
00246         }
00247 
00254         reference_t set()
00255         {
00256             return _value->set();
00257         }
00258 
00262         void set(param_t v)
00263         {
00264             _value->set(v);
00265         }
00266 
00274         reference_t value()
00275         {
00276             return set();
00277         }
00278 
00282         const_reference_t rvalue() const
00283         {
00284             return _value->rvalue();
00285         }
00286 
00296         static Property<T>* narrow( base::PropertyBase* prop );
00297 
00298         virtual void identify( base::PropertyIntrospection* pi);
00299 
00300         virtual void identify( base::PropertyBagVisitor* pi);
00301 
00302         virtual bool update( const base::PropertyBase* other)
00303         {
00304             const Property<T>* origin = dynamic_cast< const Property<T>* >( other );
00305             if ( origin != 0 ) {
00306                 return this->update( *origin );
00307             }
00308             return false;
00309         }
00310 
00311         virtual bool refresh( const base::PropertyBase* other)
00312         {
00313             const Property<T>* origin = dynamic_cast< const Property<T>* >( other );
00314             if ( origin != 0 && _value ) {
00315                 return this->refresh( *origin );
00316             }
00317             return false;
00318         }
00319 
00320         virtual bool copy( const base::PropertyBase* other )
00321         {
00322             const Property<T>* origin = dynamic_cast< const Property<T>* >( other );
00323             if ( origin != 0 && _value ) {
00324                 return this->copy( *origin );
00325             }
00326             return false;
00327         }
00328 
00332         bool copy( const Property<T>& orig)
00333         {
00334             if ( !ready() )
00335                 return false;
00336             _description = orig.getDescription();
00337             _name = orig.getName();
00338             _value->set( orig.rvalue() );
00339             return true;
00340         }
00341 
00346         bool update( const Property<T>& orig)
00347         {
00348             if ( !ready() )
00349                 return false;
00350             if ( _description.empty() )
00351                 _description = orig.getDescription();
00352             _value->set( orig.rvalue() );
00353             return true;
00354         }
00355 
00360         bool refresh( const Property<T>& orig)
00361         {
00362             if ( !ready() )
00363                 return false;
00364             _value->set( orig.rvalue() );
00365             return true;
00366         }
00367 
00368         virtual Property<T>* clone() const
00369         {
00370             return new Property<T>(*this);
00371         }
00372 
00373         virtual Property<T>* create() const
00374         {
00375             return new Property<T>( _name, _description, T() );
00376         }
00377 
00378         virtual base::DataSourceBase::shared_ptr getDataSource() const {
00379             return _value;
00380         }
00381 
00382         typename internal::AssignableDataSource<DataSourceType>::shared_ptr getAssignableDataSource() const {
00383             return _value;
00384         }
00385 
00386         virtual std::string getType() const {
00387             return internal::DataSource<T>::GetType();
00388         }
00389 
00390         virtual const types::TypeInfo* getTypeInfo() const {
00391             return internal::DataSource<T>::GetTypeInfo();
00392         }
00393     protected:
00394         typename internal::AssignableDataSource<DataSourceType>::shared_ptr _value;
00395     };
00396 
00397 
00401     template<>
00402     RTT_API bool Property<PropertyBag>::update( const Property<PropertyBag>& orig);
00403 
00404     template<>
00405     RTT_API bool Property<PropertyBag>::refresh( const Property<PropertyBag>& orig);
00406 
00407     template<>
00408     RTT_API bool Property<PropertyBag>::copy( const Property<PropertyBag>& orig);
00409 
00410     template<typename T>
00411     std::ostream& operator<<(std::ostream &os, Property<T> &p)
00412     {
00413 #ifdef OS_HAVE_STREAMS
00414         os << p.getDataSource();
00415 #endif
00416         return os;
00417     }
00418 
00419     template<class T>
00420     Property<T>* Property<T>::narrow( base::PropertyBase* prop ) {
00421         Property<T>* res = dynamic_cast<Property<T>*>( prop );
00422         return res;
00423     }
00424 }
00425 
00426 #include "base/PropertyIntrospection.hpp"
00427 
00428 namespace RTT
00429 {
00430     template< class T>
00431     void Property<T>::identify( base::PropertyIntrospection* pi)
00432     {
00433         pi->introspect( *this );
00434     }
00435 
00436     template< class T>
00437     void Property<T>::identify( base::PropertyBagVisitor* pi)
00438     {
00439         return base::PropertyBase::identify(pi);
00440     }
00441 
00442     template<>
00443     RTT_API void Property<PropertyBag>::identify( base::PropertyBagVisitor* pbi);
00444 }
00445 
00446 #endif