libDAI
include/dai/properties.h
Go to the documentation of this file.
00001 /*  This file is part of libDAI - http://www.libdai.org/
00002  *
00003  *  Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
00004  *
00005  *  Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
00006  */
00007 
00008 
00011 
00012 
00013 #ifndef __defined_libdai_properties_h
00014 #define __defined_libdai_properties_h
00015 
00016 
00017 #include <iostream>
00018 #include <sstream>
00019 #include <boost/any.hpp>
00020 #include <map>
00021 #include <vector>
00022 #include <typeinfo>
00023 #include <dai/exceptions.h>
00024 #include <dai/util.h>
00025 #include <boost/lexical_cast.hpp>
00026 
00027 
00028 namespace dai {
00029 
00030 
00032 typedef std::string PropertyKey;
00033 
00035 typedef boost::any  PropertyValue;
00036 
00038 typedef std::pair<PropertyKey, PropertyValue> Property;
00039 
00040 
00042 
00046 std::ostream& operator<< ( std::ostream & os, const Property &p );
00047 
00048 
00050 
00073 class PropertySet : private std::map<PropertyKey, PropertyValue> {
00074     public:
00076 
00077 
00078         PropertySet() {}
00079 
00081 
00083         PropertySet( const std::string& s ) {
00084             std::stringstream ss;
00085             ss << s;
00086             ss >> *this;
00087         }
00089 
00091 
00092 
00093         PropertySet& set( const PropertyKey& key, const PropertyValue& val ) { 
00094             this->operator[](key) = val; 
00095             return *this; 
00096         }
00097 
00099         PropertySet& set( const PropertySet& newProps ) {
00100             const std::map<PropertyKey, PropertyValue> *m = &newProps;
00101             foreach(value_type i, *m)
00102                 set( i.first, i.second );
00103             return *this;
00104         }
00105 
00107 
00112         PropertySet operator()( const PropertyKey& key, const PropertyValue& val ) const { 
00113             PropertySet copy = *this; 
00114             return copy.set(key,val); 
00115         }
00116 
00118 
00122         template<typename ValueType>
00123         PropertySet& setAsString( const PropertyKey& key, const ValueType& val ) {
00124             try {
00125                 return set( key, boost::lexical_cast<std::string>(val) );
00126             } catch( boost::bad_lexical_cast & ) {
00127                 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to string.");
00128             }
00129         }
00130 
00132 
00136         template<typename ValueType>
00137         void convertTo( const PropertyKey& key ) { 
00138             PropertyValue val = get(key);
00139             if( val.type() != typeid(ValueType) ) {
00140                 DAI_ASSERT( val.type() == typeid(std::string) );
00141                 try {
00142                     set(key, boost::lexical_cast<ValueType>(getAs<std::string>(key)));
00143                 } catch(boost::bad_lexical_cast &) {
00144                     DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
00145                 }
00146             }
00147         }
00149 
00151 
00153 
00154 
00155         size_t size() const {
00156             return std::map<PropertyKey, PropertyValue>::size();
00157         }
00158 
00160         void clear() {
00161             std::map<PropertyKey, PropertyValue>::clear();
00162         }
00163 
00165         size_t erase( const PropertyKey &key ) {
00166             return std::map<PropertyKey, PropertyValue>::erase( key );
00167         }
00168 
00170         bool hasKey( const PropertyKey& key ) const { 
00171             PropertySet::const_iterator x = find(key); 
00172             return (x != this->end()); 
00173         }
00174 
00176         std::set<PropertyKey> keys() const {
00177             std::set<PropertyKey> res;
00178             const_iterator i;
00179             for( i = begin(); i != end(); i++ )
00180                 res.insert( i->first );
00181             return res;
00182         }
00183 
00185 
00187         const PropertyValue& get( const PropertyKey& key ) const {
00188             PropertySet::const_iterator x = find(key);
00189             if( x == this->end() )
00190                 DAI_THROWE(OBJECT_NOT_FOUND,"PropertySet::get cannot find property '" + key + "'");
00191             return x->second;
00192         }
00193 
00195 
00199         template<typename ValueType>
00200         ValueType getAs( const PropertyKey& key ) const {
00201             try {
00202                 return boost::any_cast<ValueType>(get(key));
00203             } catch( const boost::bad_any_cast & ) {
00204                 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to desired type.");
00205                 return ValueType();
00206             }
00207         }
00208 
00210 
00217         template<typename ValueType>
00218         ValueType getStringAs( const PropertyKey& key ) const { 
00219             PropertyValue val = get(key);
00220             if( val.type() == typeid(ValueType) ) {
00221                 return boost::any_cast<ValueType>(val);
00222             } else if( val.type() == typeid(std::string) ) {
00223                 try {
00224                     return boost::lexical_cast<ValueType>(getAs<std::string>(key));
00225                 } catch(boost::bad_lexical_cast &) {
00226                     DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
00227                 }
00228             } else
00229                 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
00230             return ValueType();
00231         }
00233 
00235 
00236 
00237 
00242         friend std::ostream& operator<< ( std::ostream& os, const PropertySet& ps );
00243 
00245 
00249         friend std::istream& operator>> ( std::istream& is, PropertySet& ps );
00251 };
00252 
00253 
00254 } // end of namespace dai
00255 
00256 
00257 #endif