TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/property/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         OfxhSet& operator=( const This& );
00129 
00130         bool operator==( const This& ) const;
00131         bool operator!=( const This& other ) const { return !This::operator==( other ); }
00132 
00133         void copyValues( const This& other );
00134 
00135         #ifndef SWIG
00136         friend std::ostream& operator<<( std::ostream& os, const This& g );
00137         #endif
00138 
00139         OfxhProperty& localAt( const int index );
00140         const OfxhProperty& at( const int index ) const;
00141 
00142         /// adds a bunch of properties from PropSpec
00143         void addProperties( const OfxhPropSpec* );
00144 
00145         void eraseProperty( const std::string& propName );
00146 
00147         bool hasProperty( const std::string& propName, bool followChain = true ) const;
00148         bool hasLocalProperty( const std::string& propName ) const;
00149 
00150         inline OfxhSet& operator+=( const OfxhPropSpec* p ) { addProperties( p ); return *this; }
00151 
00152         /// add one new property
00153         void createProperty( const OfxhPropSpec& s );
00154 
00155         /// add one new property (takes ownership)
00156         void addProperty( OfxhProperty* prop );
00157 
00158         /// set the chained property set
00159         void setChainedSet( const OfxhSet* const s ) { _chainedSet = s; }
00160 
00161         const OfxhSet& getChainedSet() const { return *_chainedSet; }
00162 
00163         /// grab the internal properties map
00164         const PropertyMap& getMap() const { return _props; }
00165         PropertyMap&       getMap()       { return _props; }
00166 
00167         /// set the get hook for a particular property.  users may need to call particular
00168         /// specialised versions of this.
00169         void setGetHook( const std::string& s, OfxhGetHook* ghook );
00170 
00171         /// add a set hook for a particular property.  users may need to call particular
00172         /// specialised versions of this.
00173         void addNotifyHook( const std::string& name, OfxhNotifyHook* hook );
00174 
00175         /// Fetchs a reference to a property of the given name, following the property chain if the
00176         /// 'followChain' arg is not false.
00177         const OfxhProperty& fetchProperty( const std::string& name ) const;
00178         OfxhProperty&       fetchLocalProperty( const std::string& name );
00179         const OfxhProperty& fetchLocalProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalProperty( name ); }
00180 
00181         /// get property with the particular name and type.  if the property is
00182         /// missing or is of the wrong type, return an error status.  if this is a sloppy
00183         /// property set and the property is missing, a new one will be created of the right
00184         /// type
00185         template<class T>
00186         const T& fetchTypedProperty( const std::string& name ) const
00187         {
00188                 return dynamic_cast<const T&>( fetchProperty( name ) );
00189         }
00190 
00191         template<class T>
00192         T& fetchLocalTypedProperty( const std::string& name )
00193         {
00194                 return dynamic_cast<T&>( fetchLocalProperty( name ) );
00195         }
00196 
00197         template<class T>
00198         const T& fetchLocalTypedProperty( const std::string& name ) const
00199         {
00200                 return const_cast<OfxhSet*>( this )->fetchLocalTypedProperty<T>( name );
00201         }
00202 
00203 
00204         const String& fetchStringProperty( const std::string& name ) const
00205         {
00206                 return fetchTypedProperty<String>( name );
00207         }
00208 
00209         String& fetchLocalStringProperty( const std::string& name )
00210         {
00211                 return fetchLocalTypedProperty<String>( name );
00212         }
00213 
00214         const String& fetchLocalStringProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalStringProperty( name ); }
00215 
00216         const Int& fetchIntProperty( const std::string& name ) const
00217         {
00218                 return fetchTypedProperty<Int>( name );
00219         }
00220 
00221         Int& fetchLocalIntProperty( const std::string& name )
00222         {
00223                 return fetchLocalTypedProperty<Int>( name );
00224         }
00225 
00226         const Int& fetchLocalIntProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalIntProperty( name ); }
00227 
00228         const Pointer& fetchPointerProperty( const std::string& name ) const
00229         {
00230                 return fetchTypedProperty<Pointer>( name );
00231         }
00232 
00233         Pointer& fetchLocalPointerProperty( const std::string& name )
00234         {
00235                 return fetchLocalTypedProperty<Pointer>( name );
00236         }
00237 
00238         const Pointer& fetchLocalPointerProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalPointerProperty( name ); }
00239 
00240         const Double& fetchDoubleProperty( const std::string& name ) const
00241         {
00242                 return fetchTypedProperty<Double>( name );
00243         }
00244 
00245         Double& fetchLocalDoubleProperty( const std::string& name )
00246         {
00247                 return fetchLocalTypedProperty<Double>( name );
00248         }
00249 
00250         const Double& fetchLocalDoubleProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalDoubleProperty( name ); }
00251 
00252         
00253         /// get a particular int property without fetching via a get hook, useful for notifies
00254         int getIntPropertyRaw( const std::string& property, int index = 0 ) const;
00255 
00256         /// get a particular double property without fetching via a get hook, useful for notifies
00257         double getDoublePropertyRaw( const std::string& property, int index = 0 ) const;
00258 
00259         /// get a particular pointer property without fetching via a get hook, useful for notifies
00260         void* getPointerPropertyRaw( const std::string& property, int index = 0 ) const; /// @todo tuttle: return const no ?
00261 
00262         /// get a particular string property
00263         const std::string& getStringPropertyRaw( const std::string& property, int index = 0 ) const;
00264 
00265         /// get the value of a particular string property
00266         const std::string& getStringProperty( const std::string& property, int index = 0 ) const;
00267 
00268         /// get the value of a particular int property
00269         int getIntProperty( const std::string& property, int index = 0 ) const;
00270 
00271         /// get the value of a particular double property
00272         void getIntPropertyN( const std::string& property,  int* v, int N ) const;
00273 
00274         /// get the value of a particular double property
00275         double getDoubleProperty( const std::string& property, int index = 0 ) const;
00276 
00277         /// get the value of a particular double property
00278         void getDoublePropertyN( const std::string& property,  double* v, int N ) const;
00279 
00280         /// get the value of a particular pointer property
00281         void* getPointerProperty( const std::string& property, int index = 0 ) const;
00282 
00283         /// set a particular string property without fetching via a get hook, useful for notifies
00284         void setStringProperty( const std::string& property, const std::string& value, int index = 0 ) { setProperty<OfxhStringValue >( property, index, value ); }
00285 
00286         /// set a particular int property
00287         void setIntProperty( const std::string& property, int v, int index = 0 ) { setProperty<OfxhIntValue >( property, index, v ); }
00288 
00289         /// set a particular double property
00290         void setIntPropertyN( const std::string& property, const int* v, int N )
00291         {
00292                 setPropertyN<OfxhIntValue >( property, N, v );
00293         }
00294 
00295         /// get a particular double property
00296         void setDoubleProperty( const std::string& property, double v, int index = 0 ) { setProperty<OfxhDoubleValue >( property, index, v ); }
00297 
00298         /// get a particular double property
00299         void setDoublePropertyN( const std::string& property, const double* v, int N ) { setPropertyN<OfxhDoubleValue >( property, N, v ); }
00300 
00301         /// get a particular double property
00302         void setPointerProperty( const std::string& property, void* v, int index = 0 ) { setProperty<OfxhPointerValue >( property, index, v ); }
00303 
00304         /// get the dimension of a particular property
00305         size_t getDimension( const std::string& property ) const { return fetchProperty( property ).getDimension(); }
00306 
00307         /// is the given string one of the values of a multi-dimensional string prop
00308         /// this returns a non negative index if it is found, otherwise, -1
00309         int findStringPropValueIndex( const std::string& propName,
00310                                       const std::string& propValue ) const;
00311 
00312         /// get a handle on this object for passing to the C API
00313         OfxPropertySetHandle getHandle() const { return ( OfxPropertySetHandle ) this; }
00314 
00315         /// is this a nice property set, or a dodgy pointer passed back to us
00316         bool verifyMagic() { return this != NULL && _magic == kMagic; }
00317 
00318 private:
00319         friend class boost::serialization::access;
00320         template<class Archive>
00321         void serialize( Archive& ar, const unsigned int version )
00322         {
00323                 ar& BOOST_SERIALIZATION_NVP( _props );
00324         }
00325 
00326 };
00327 
00328 /// set a particular property
00329 template<class T>
00330 void OfxhSet::setProperty( const std::string& property, int index, const typename T::Type& value )
00331 {
00332         try
00333         {
00334                 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValue( value, index );
00335         }
00336         catch( OfxhException& e )
00337         {
00338                 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ").");
00339                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00340                 TUTTLE_LOG_EXCEPTION( e );
00341                 //TUTTLE_LOG_DEBUG( *this );
00342         }
00343         catch(... )
00344         {
00345                 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ")." <<
00346                             "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00347                 //TUTTLE_LOG_DEBUG( *this );
00348         }
00349 }
00350 
00351 /// set a particular property
00352 
00353 template<class T>
00354 void OfxhSet::setPropertyN( const std::string& property, int count, const typename T::APIType* value )
00355 {
00356         try
00357         {
00358                 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValueN( value, count );
00359         }
00360         catch( OfxhException& e )
00361         {
00362                 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." );
00363                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00364                 TUTTLE_LOG_EXCEPTION( e );
00365         }
00366         catch(... )
00367         {
00368                 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." );
00369                 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." );
00370         }
00371 }
00372 
00373 /// get a particular property
00374 
00375 template<class T>
00376 typename T::ReturnType OfxhSet::getProperty( const std::string& property, int index ) const
00377 {
00378         /*
00379         if( !hasProperty( property, true ) )
00380         {
00381                 TUTTLE_TLOG( TUTTLE_INFO, "return kEmpty on property: " << property );
00382                 return T::kEmpty; /// @todo tuttle: is this really needed ?
00383         }
00384         */
00385         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValue( index );
00386 }
00387 
00388 /// get a particular property
00389 
00390 template<class T>
00391 void OfxhSet::getPropertyN( const std::string& property, int count, typename T::APIType* value ) const
00392 {
00393         fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueN( value, count );
00394 }
00395 
00396 /// get a particular property
00397 
00398 template<class T>
00399 typename T::ReturnType OfxhSet::getPropertyRaw( const std::string& property, int index ) const
00400 {
00401         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueRaw( index );
00402 }
00403 
00404 /// get a particular property
00405 
00406 template<class T>
00407 void OfxhSet::getPropertyRawN( const std::string& property, int count, typename T::APIType* value ) const
00408 {
00409         return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueNRaw( value, count );
00410 }
00411 
00412 }
00413 }
00414 }
00415 }
00416 
00417 #endif