TuttleOFX  1
OfxhSet.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License :
00003  *
00004  * Copyright (c) 2007-2009, The Open Effects Association Ltd.  All Rights Reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  * Neither the name The Open Effects Association Ltd, nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #ifndef _TUTTLE_HOST_OFX_PROPERTY_SET_HPP_
00030 #define _TUTTLE_HOST_OFX_PROPERTY_SET_HPP_
00031 
00032 #include "OfxhPropertyTemplate.hpp"
00033 
00034 #include <boost/ptr_container/serialize_ptr_map.hpp>
00035 
00036 namespace tuttle {
00037 namespace host {
00038 namespace ofx {
00039 namespace property {
00040 
00041 /// A class that is used to initialize a property set. Feed in an array of these to
00042 /// a property and it will construct a bunch of properties. Terminate such an array
00043 /// with an empty (all zero) set.
00044 struct OfxhPropSpec
00045 {
00046         const char* name;          ///< name of the property
00047         EPropType type;             ///< type
00048         int dimension;             ///< fixed dimension of the property, set to zero if variable dimension
00049         bool readonly;             ///< is the property plug-in read only
00050         const char* defaultValue;  ///< Default value as a string. Pointers are ignored and always null.
00051 };
00052 
00053 /// A std::map of properties by name
00054 typedef boost::ptr_map<std::string, OfxhProperty> PropertyMap;
00055 
00056 /**
00057  * Class that holds a set of properties and manipulates them
00058  * The 'fetch' methods return a property object.
00059  * The 'get' methods return a property value
00060  */
00061 class OfxhSet
00062 {
00063 public:
00064         typedef OfxhSet This;
00065 
00066 private:
00067         static const int kMagic = 0x12082007; ///< magic number for property sets, and Connie's birthday :-)
00068         const int _magic; ///< to check for handles being nice
00069 
00070 protected:
00071         PropertyMap _props; ///< Our properties.
00072 
00073         /// chained property set, which is read only
00074         /// these are searched on a get if not found
00075         /// on a local search
00076         const OfxhSet* _chainedSet;
00077 
00078         /// set a particular property
00079         template<class T>
00080         void setProperty( const std::string& property, int index, const typename T::Type& value );
00081 
00082         /// set the first N of a particular property
00083         template<class T>
00084         void setPropertyN( const std::string& property, int count, const typename T::APIType* value );
00085 
00086         /// get a particular property
00087         template<class T>
00088         typename T::ReturnType getProperty( const std::string& property, int index )  const;
00089 
00090         /// get the first N of a particular property
00091         template<class T>
00092         void getPropertyN( const std::string & property, int index, typename T::APIType * v )  const;
00093 
00094         /// get a particular property without going through any getHook
00095         template<class T>
00096         typename T::ReturnType getPropertyRaw( const std::string& property, int index )  const;
00097 
00098         /// get a particular property without going through any getHook
00099         template<class T>
00100         void getPropertyRawN( const std::string & property, int count, typename T::APIType * v )  const;
00101 
00102 public:
00103         /// take an array of of PropSpecs (which must be terminated with an entry in which
00104         /// ->name is null), and turn these into a Set
00105         OfxhSet( const OfxhPropSpec spec[] );
00106         //        explicit Set(const std::vector<const PropSpec*>& multipleSpec);
00107 
00108         /// deep copies the property set
00109         OfxhSet( const OfxhSet& );
00110 
00111         /// empty ctor
00112         OfxhSet();
00113 
00114         /// destructor
00115         virtual ~OfxhSet();
00116 
00117         void clear();
00118 
00119         size_t getLocalSize() const { return _props.size(); }
00120         size_t getSize() const
00121         {
00122                 if( _chainedSet == NULL )
00123                         return getLocalSize();
00124                 else
00125                         return getLocalSize() + _chainedSet->getSize();
00126         }
00127 
00128         /// hide assignment
00129         void operator=( const This& );
00130 
00131         bool operator==( const This& ) const;
00132         bool operator!=( const This& other ) const { return !This::operator==( other ); }
00133 
00134         void copyValues( const This& other );
00135 
00136         #ifndef SWIG
00137         friend std::ostream& operator<<( std::ostream& os, const This& g );
00138         #endif
00139 
00140         #ifdef SWIG
00141         %extend
00142         {
00143                 //              const OfxhProperty& __getitem__( const std::string& name ) const
00144                 //              {
00145                 //                      return self->fetchProperty(name);
00146                 //              }
00147                 OfxhProperty& __getitem__( const std::string& name )
00148                 {
00149                         return self->fetchLocalProperty( name );
00150                 }
00151 
00152                 std::string __str__() const
00153                 {
00154                         std::stringstream s;
00155 
00156                         s << *self;
00157                         return s.str();
00158                 }
00159 
00160         }
00161         #endif
00162 
00163         /// adds a bunch of properties from PropSpec
00164         void addProperties( const OfxhPropSpec* );
00165 
00166         void eraseProperty( const std::string& propName );
00167 
00168         bool hasProperty( const std::string& propName, bool followChain = true ) const;
00169         bool hasLocalProperty( const std::string& propName ) const;
00170 
00171         inline OfxhSet& operator+( const OfxhPropSpec* p ) { addProperties( p ); return *this; }
00172 
00173         /// add one new property
00174         void createProperty( const OfxhPropSpec& s );
00175 
00176         /// add one new property
00177         void addProperty( OfxhProperty* prop );
00178 
00179         /// set the chained property set
00180         void setChainedSet( const OfxhSet* const s ) { _chainedSet = s; }
00181 
00182         /// grab the internal properties map
00183         const PropertyMap& getMap() const { return _props; }
00184         PropertyMap&       getMap()       { return _props; }
00185 
00186         /// set the get hook for a particular property.  users may need to call particular
00187         /// specialised versions of this.
00188         void setGetHook( const std::string& s, OfxhGetHook* ghook );
00189 
00190         /// add a set hook for a particular property.  users may need to call particular
00191         /// specialised versions of this.
00192         void addNotifyHook( const std::string& name, OfxhNotifyHook* hook );
00193 
00194         /// Fetchs a reference to a property of the given name, following the property chain if the
00195         /// 'followChain' arg is not false.
00196         const OfxhProperty& fetchProperty( const std::string& name ) const;
00197         OfxhProperty&       fetchLocalProperty( const std::string& name );
00198         const OfxhProperty& fetchLocalProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalProperty( name ); }
00199 
00200         /// get property with the particular name and type.  if the property is
00201         /// missing or is of the wrong type, return an error status.  if this is a sloppy
00202         /// property set and the property is missing, a new one will be created of the right
00203         /// type
00204         template<class T>
00205         const T& fetchTypedProperty( const std::string& name ) const
00206         {
00207                 return dynamic_cast<const T&>( fetchProperty( name ) );
00208         }
00209 
00210         template<class T>
00211         T& fetchLocalTypedProperty( const std::string& name )
00212         {
00213                 return dynamic_cast<T&>( fetchLocalProperty( name ) );
00214         }
00215 
00216         template<class T>
00217         const T& fetchLocalTypedProperty( const std::string& name ) const
00218         {
00219                 return const_cast<OfxhSet*>( this )->fetchLocalTypedProperty<T>( name );
00220         }
00221 
00222 
00223         const String& fetchStringProperty( const std::string& name ) const
00224         {
00225                 return fetchTypedProperty<String>( name );
00226         }
00227 
00228         String& fetchLocalStringProperty( const std::string& name )
00229         {
00230                 return fetchLocalTypedProperty<String>( name );
00231         }
00232 
00233         const String& fetchLocalStringProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalStringProperty( name ); }
00234 
00235         const Int& fetchIntProperty( const std::string& name ) const
00236         {
00237                 return fetchTypedProperty<Int>( name );
00238         }
00239 
00240         Int& fetchLocalIntProperty( const std::string& name )
00241         {
00242                 return fetchLocalTypedProperty<Int>( name );
00243         }
00244 
00245         const Int& fetchLocalIntProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalIntProperty( name ); }
00246 
00247         const Pointer& fetchPointerProperty( const std::string& name ) const
00248         {
00249                 return fetchTypedProperty<Pointer>( name );
00250         }
00251 
00252         Pointer& fetchLocalPointerProperty( const std::string& name )
00253         {
00254                 return fetchLocalTypedProperty<Pointer>( name );
00255         }
00256 
00257         const Pointer& fetchLocalPointerProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalPointerProperty( name ); }
00258 
00259         const Double& fetchDoubleProperty( const std::string& name ) const
00260         {
00261                 return fetchTypedProperty<Double>( name );
00262         }
00263 
00264         Double& fetchLocalDoubleProperty( const std::string& name )
00265         {
00266                 return fetchLocalTypedProperty<Double>( name );
00267         }
00268 
00269         const Double& fetchLocalDoubleProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalDoubleProperty( name ); }
00270 
00271         
00272         /// get a particular int property without fetching via a get hook, useful for notifies
00273         int getIntPropertyRaw( const std::string& property, int index = 0 ) const;
00274 
00275         /// get a particular double property without fetching via a get hook, useful for notifies
00276         double getDoublePropertyRaw( const std::string& property, int index = 0 ) const;
00277 
00278         /// get a particular pointer property without fetching via a get hook, useful for notifies
00279         void* getPointerPropertyRaw( const std::string& property, int index = 0 ) const; /// @todo tuttle: return const no ?
00280 
00281         /// get a particular string property
00282         const std::string& getStringPropertyRaw( const std::string& property, int index = 0 ) const;
00283 
00284         /// get the value of a particular string property
00285         const std::string& getStringProperty( const std::string& property, int index = 0 ) const;
00286 
00287         /// get the value of a particular int property
00288         int getIntProperty( const std::string& property, int index = 0 ) const;
00289 
00290         /// get the value of a particular double property
00291         void getIntPropertyN( const std::string& property,  int* v, int N ) const;
00292 
00293         /// get the value of a particular double property
00294         double getDoubleProperty( const std::string& property, int index = 0 ) const;
00295 
00296         /// get the value of a particular double property
00297         void getDoublePropertyN( const std::string& property,  double* v, int N ) const;
00298 
00299         /// get the value of a particular pointer property
00300         void* getPointerProperty( const std::string& property, int index = 0 ) const;
00301 
00302         /// set a particular string property without fetching via a get hook, useful for notifies
00303         void setStringProperty( const std::string& property, const std::string& value, int index = 0 ) { setProperty<OfxhStringValue >( property, index, value ); }
00304 
00305         /// set a particular int property
00306         void setIntProperty( const std::string& property, int v, int index = 0 ) { setProperty<OfxhIntValue >( property, index, v ); }
00307 
00308         /// set a particular double property
00309         void setIntPropertyN( const std::string& property, const int* v, int N )
00310         {
00311                 setPropertyN<OfxhIntValue >( property, N, v );
00312         }
00313 
00314         /// get a particular double property
00315         void setDoubleProperty( const std::string& property, double v, int index = 0 ) { setProperty<OfxhDoubleValue >( property, index, v ); }
00316 
00317         /// get a particular double property
00318         void setDoublePropertyN( const std::string& property, const double* v, int N ) { setPropertyN<OfxhDoubleValue >( property, N, v ); }
00319 
00320         /// get a particular double property
00321         void setPointerProperty( const std::string& property, void* v, int index = 0 ) { setProperty<OfxhPointerValue >( property, index, v ); }
00322 
00323         /// get the dimension of a particular property
00324         size_t getDimension( const std::string& property ) const { return fetchProperty( property ).getDimension(); }
00325 
00326         /// is the given string one of the values of a multi-dimensional string prop
00327         /// this returns a non negative index if it is found, otherwise, -1
00328         int findStringPropValueIndex( const std::string& propName,
00329                                       const std::string& propValue ) const;
00330 
00331         /// get a handle on this object for passing to the C API
00332         OfxPropertySetHandle getHandle() const { return ( OfxPropertySetHandle ) this; }
00333 
00334         /// is this a nice property set, or a dodgy pointer passed back to us
00335         bool verifyMagic() { return this != NULL && _magic == kMagic; }
00336 
00337 private:
00338         friend class boost::serialization::access;
00339         template<class Archive>
00340         void serialize( Archive& ar, const unsigned int version )
00341         {
00342                 ar& BOOST_SERIALIZATION_NVP( _props );
00343         }
00344 
00345 };
00346 
00347 /// set a particular property
00348 template<class T>
00349 void OfxhSet::setProperty( const std::string& property, int index, const typename T::Type& value )
00350 {
00351         try
00352         {
00353                 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValue( value, index );
00354         }
00355         catch( OfxhException& e )
00356         {
00357                 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ").");
00358                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00359                 TUTTLE_LOG_EXCEPTION( e );
00360                 //TUTTLE_LOG_DEBUG( *this );
00361         }
00362         catch(... )
00363         {
00364                 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ")." <<
00365                             "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00366                 //TUTTLE_LOG_DEBUG( *this );
00367         }
00368 }
00369 
00370 /// set a particular property
00371 
00372 template<class T>
00373 void OfxhSet::setPropertyN( const std::string& property, int count, const typename T::APIType* value )
00374 {
00375         try
00376         {
00377                 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValueN( value, count );
00378         }
00379         catch( OfxhException& e )
00380         {
00381                 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." );
00382                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00383                 TUTTLE_LOG_EXCEPTION( e );
00384         }
00385         catch(... )
00386         {
00387                 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." );
00388                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00389         }
00390 }
00391 
00392 /// get a particular property
00393 
00394 template<class T>
00395 typename T::ReturnType OfxhSet::getProperty( const std::string& property, int index ) const
00396 {
00397         /*
00398         if( !hasProperty( property, true ) )
00399         {
00400                 TUTTLE_TLOG( TUTTLE_INFO, "return kEmpty on property: " << property );
00401                 return T::kEmpty; /// @todo tuttle: is this really needed ?
00402         }
00403         */
00404         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValue( index );
00405 }
00406 
00407 /// get a particular property
00408 
00409 template<class T>
00410 void OfxhSet::getPropertyN( const std::string& property, int count, typename T::APIType* value ) const
00411 {
00412         fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueN( value, count );
00413 }
00414 
00415 /// get a particular property
00416 
00417 template<class T>
00418 typename T::ReturnType OfxhSet::getPropertyRaw( const std::string& property, int index ) const
00419 {
00420         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueRaw( index );
00421 }
00422 
00423 /// get a particular property
00424 
00425 template<class T>
00426 void OfxhSet::getPropertyRawN( const std::string& property, int count, typename T::APIType* value ) const
00427 {
00428         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueNRaw( value, count );
00429 }
00430 
00431 }
00432 }
00433 }
00434 }
00435 
00436 #endif