Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members

property_server.h

00001 #ifndef s11n_PROPERTY_SERVER_H_INCLUDED
00002 #define s11n_PROPERTY_SERVER_H_INCLUDED 1
00003 #include <string>
00004 
00005 #include <s11n/to_string.h> // to/from_string()
00006 #include <s11n/phoenix.h> // phoenix class
00007 
00008 namespace s11n {
00009 
00010         /**
00011            property_server is an experimental class for tying
00012            arbitrary properties to arbitrary objects. It supports, as
00013            values, any data types which are i/ostreamable using their
00014            <code> >>istream</code> or <code>ostream<< </code>
00015            operators.
00016 
00017            License: Do As You Damned Well Please
00018            Author: stephan@s11n.net
00019 
00020         */
00021 
00022         template <typename ContextType, typename ObjIDType = ContextType *, typename KeyType = std::string>
00023         class property_server
00024         {
00025         public:
00026                 /**
00027                    The "sharing context" used by this type.
00028                 */
00029                 typedef ContextType context_type;
00030 
00031                 /** The type used to key objects to their properties. */
00032                 typedef ObjIDType object_id_type;
00033 
00034                 /** The key type used for properties. */
00035                 typedef KeyType key_type;
00036 
00037                 /** The underlying data store for properties. */
00038                 typedef std::map<key_type,std::string> property_map_type;
00039 
00040 
00041                 /**
00042                    Sets the property key to val for objid.
00043                 */
00044                 template <typename ValueType>
00045                 static void set( const object_id_type objid, const key_type & key, const ValueType & val )
00046                 {
00047                         object_map()[objid][key] = s11n::to_string( val );
00048                 }
00049 
00050                 /**
00051                    Returns the property key for objid. If there is an error
00052                    converting the value to ValueType, or if the property does
00053                    not exist, defaultval is returned. This can be used to
00054                    implement custom error handling by passing a known-invalid
00055                    value as defaultval and interpretting it as an error
00056                    value. If there is *no* known-invalid combinations then you
00057                    can check twice with two different defaulvals. If
00058                    defaultval is returned both times then there is definately
00059                    an error, because valid data would only be interpretted one
00060                    way and you've checked against two different defaultvals.
00061                 */
00062                 template <typename ValueType>
00063                 static ValueType get( const object_id_type objid, const key_type & key, const ValueType & defaultval )
00064                 {
00065                         typename object_map_type::const_iterator it = object_map().find( objid );
00066                         if( object_map().end() == it ) return defaultval;
00067                         const property_map_type & pmap = it.second;
00068                         typename property_map_type::const_iterator pit = pmap.find( key );
00069                         if( pmap.end() == pit ) return defaultval;
00070                         return s11n::from_string<ValueType>( pit.second, defaultval );
00071                 }
00072 
00073                 /**
00074                    Removes the given property from the given object.
00075                 */
00076                 static void unset( const object_id_type objid, const key_type & key )
00077                 {
00078                         typename object_map_type::const_iterator it = object_map().find( objid );
00079                         if( object_map().end() == it ) return;
00080                         const property_map_type & pmap = it.second;
00081                         typename property_map_type::const_iterator pit = pmap.find( key );
00082                         if( pmap.end() == pit ) return;
00083                         pmap.erase( pit );
00084                 }
00085 
00086                 /**
00087                    Removes the property map for objid, freeing up any
00088                    resources it consumed.
00089                 */
00090                 static void clear( const object_id_type objid )
00091                 {
00092                         typename object_map_type::iterator it = object_map().find( objid );
00093                         if( object_map().end() == it ) return;
00094                         object_map().erase( it );
00095                 }
00096 
00097                 /** Removes all properties for all objects. */
00098                 static void clear_all()
00099                 {
00100                         object_map().clear();
00101                 }
00102 
00103                 //      typedef void (change_listener_callback)( object_id_type, const key_type key & );
00104                 //        void add_change_listener( change_listener_callback cb );
00105 
00106                 /**
00107                    Returns a pointer to the given object's property map, or 0
00108                    if no properties have been set for the object (or if
00109                    clear(objid) has been called).
00110 
00111                    The caller does not own the returned pointer and (ideally)
00112                    should not modify the map directly (prefer get() and
00113                    set()). It is provided here primarily for serialization
00114                    purposes: so the map can be saved and loaded using
00115                    arbitrary serialization techniques.
00116                 */
00117                 static property_map_type * get_map( const object_id_type objid )
00118                 {
00119                         typename object_map_type::iterator it = object_map().find( objid );
00120                         if( object_map().end() == it ) return 0;
00121                         property_map_type * pm = & ((*it).second);
00122                         return pm;
00123                 }
00124 
00125         private:
00126                 typedef property_server< ContextType, ObjIDType > this_type;
00127                 typedef std::map<object_id_type,property_map_type> object_map_type;
00128 
00129                 static object_map_type & object_map()
00130                 {
00131                         return s11n::phoenix<object_map_type,this_type>::instance();
00132                 }
00133 
00134         };
00135 
00136 } // namespace s11n_s11n
00137 
00138 #endif // PROPERTY_SERVER_H_INCLUDED

Generated on Thu Jun 16 16:18:12 2005 for s11n by  doxygen 1.4.3-20050530