Updated copyright headers
[libdai.git] / include / dai / properties.h
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
6 *
7 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
8 * Copyright (C) 2006-2007 Radboud University Nijmegen, The Netherlands
9 */
10
11
12 /// \file
13 /// \brief Defines the Property and PropertySet classes
14 /// \todo Improve documentation
15
16
17 #ifndef __defined_libdai_properties_h
18 #define __defined_libdai_properties_h
19
20
21 #include <iostream>
22 #include <sstream>
23 #include <boost/any.hpp>
24 #include <map>
25 #include <vector>
26 #include <cassert>
27 #include <typeinfo>
28 #include <dai/exceptions.h>
29 #include <dai/util.h>
30 #include <boost/lexical_cast.hpp>
31
32
33 namespace dai {
34
35
36 /// Type of the key of a Property
37 typedef std::string PropertyKey;
38
39 /// Type of the value of a Property
40 typedef boost::any PropertyValue;
41
42 /// A Property is a pair of a key and a corresponding value
43 typedef std::pair<PropertyKey, PropertyValue> Property;
44
45
46 /// Writes a Property object to an output stream
47 std::ostream& operator<< (std::ostream & os, const Property & p);
48
49
50 /// Represents a set of properties, mapping keys (of type PropertyKey) to values (of type PropertyValue)
51 class PropertySet : private std::map<PropertyKey, PropertyValue> {
52 public:
53 /// Default constructor
54 PropertySet() {}
55
56 /// Construct PropertySet from a string
57 PropertySet( const std::string &s ) {
58 std::stringstream ss;
59 ss << s;
60 ss >> *this;
61 }
62
63 /// Gets a property
64 const PropertyValue & Get(const PropertyKey &key) const {
65 PropertySet::const_iterator x = find(key);
66 if( x == this->end() )
67 DAI_THROWE(OBJECT_NOT_FOUND,"PropertySet::Get cannot find property '" + key + "'");
68 return x->second;
69 }
70
71 /// Sets a property
72 PropertySet & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
73
74 /// Set properties according to those in newProps, overriding properties that already exist with new values
75 PropertySet & Set( const PropertySet &newProps ) {
76 const std::map<PropertyKey, PropertyValue> *m = &newProps;
77 foreach(value_type i, *m)
78 Set( i.first, i.second );
79 return *this;
80 }
81
82 /// Gets a property, casted as ValueType
83 template<typename ValueType>
84 ValueType GetAs(const PropertyKey &key) const {
85 try {
86 return boost::any_cast<ValueType>(Get(key));
87 } catch( const boost::bad_any_cast & ) {
88 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to desired type.");
89 return ValueType();
90 }
91 }
92
93 /// Converts a property from string to ValueType (if necessary)
94 template<typename ValueType>
95 void ConvertTo(const PropertyKey &key) {
96 PropertyValue val = Get(key);
97 if( val.type() != typeid(ValueType) ) {
98 assert( val.type() == typeid(std::string) );
99 try {
100 Set(key, boost::lexical_cast<ValueType>(GetAs<std::string>(key)));
101 } catch(boost::bad_lexical_cast &) {
102 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
103 }
104 }
105 }
106
107 /// Converts a property from string to ValueType (if necessary)
108 template<typename ValueType>
109 ValueType getStringAs(const PropertyKey &key) const {
110 PropertyValue val = Get(key);
111 if( val.type() == typeid(ValueType) ) {
112 return boost::any_cast<ValueType>(val);
113 } else if( val.type() == typeid(std::string) ) {
114 try {
115 return boost::lexical_cast<ValueType>(GetAs<std::string>(key));
116 } catch(boost::bad_lexical_cast &) {
117 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
118 }
119 } else
120 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
121 return ValueType();
122 }
123
124 /// Converts a property from ValueType to string (if necessary)
125 template<typename ValueType>
126 PropertySet & setAsString(const PropertyKey &key, ValueType &val) {
127 try {
128 return Set( key, boost::lexical_cast<std::string>(val) );
129 } catch( boost::bad_lexical_cast & ) {
130 DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to string.");
131 }
132 }
133
134 /// Shorthand for (temporarily) adding properties, e.g. PropertySet p()("method","BP")("verbose",1)("tol",1e-9)
135 PropertySet operator()(const PropertyKey &key, const PropertyValue &val) const { PropertySet copy = *this; return copy.Set(key,val); }
136
137 /// Check if a property with the given key exists
138 bool hasKey(const PropertyKey &key) const { PropertySet::const_iterator x = find(key); return (x != this->end()); }
139
140 /// Returns a set containing all keys
141 std::set<PropertyKey> allKeys() const {
142 std::set<PropertyKey> res;
143 const_iterator i;
144 for( i = begin(); i != end(); i++ )
145 res.insert( i->first );
146 return res;
147 }
148
149 /// Returns a vector containing all keys
150 std::vector<PropertyKey> keys() const {
151 std::vector<PropertyKey> result;
152 result.reserve( size() );
153 for( PropertySet::const_iterator i = begin(); i != end(); ++i )
154 result.push_back( i->first );
155 return result;
156 }
157
158 /// Writes a PropertySet object to an output stream
159 friend std::ostream& operator<< (std::ostream & os, const PropertySet & ps);
160
161 /// Reads a PropertySet object from an input stream, storing values as strings
162 friend std::istream& operator>> (std::istream& is, PropertySet & ps);
163 };
164
165
166 } // end of namespace dai
167
168
169 #endif