Merge branch 'joris'
[libdai.git] / include / dai / properties.h
1 /* Copyright (C) 2006-2008 Joris Mooij [joris dot mooij at tuebingen dot mpg dot de]
2 Radboud University Nijmegen, The Netherlands /
3 Max Planck Institute for Biological Cybernetics, Germany
4
5 This file is part of libDAI.
6
7 libDAI is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 libDAI is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with libDAI; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 /// \file
24 /// \brief Defines the Property and PropertySet classes
25 /// \todo Improve documentation
26
27
28 #ifndef __defined_libdai_properties_h
29 #define __defined_libdai_properties_h
30
31
32 #include <iostream>
33 #include <sstream>
34 #include <boost/any.hpp>
35 #include <map>
36 #include <cassert>
37 #include <typeinfo>
38 #include <dai/exceptions.h>
39
40
41 namespace dai {
42
43
44 /// Type of the key of a Property
45 typedef std::string PropertyKey;
46
47 /// Type of the value of a Property
48 typedef boost::any PropertyValue;
49
50 /// A Property is a pair of a key and a corresponding value
51 typedef std::pair<PropertyKey, PropertyValue> Property;
52
53
54 /// Writes a Property object to an output stream
55 std::ostream& operator<< (std::ostream & os, const Property & p);
56
57
58 /// Represents a set of properties, mapping keys (of type PropertyKey) to values (of type PropertyValue)
59 class PropertySet : private std::map<PropertyKey, PropertyValue> {
60 public:
61 /// Gets a property
62 const PropertyValue & Get(const PropertyKey &key) const {
63 PropertySet::const_iterator x = find(key);
64 #ifdef DAI_DEBUG
65 if( x == this->end() )
66 std::cerr << "PropertySet::Get cannot find property " << key << std::endl;
67 #endif
68 assert( x != this->end() );
69 return x->second;
70 }
71
72 /// Sets a property
73 PropertySet & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
74
75 /// Gets a property, casted as ValueType
76 template<typename ValueType>
77 ValueType GetAs(const PropertyKey &key) const {
78 try {
79 return boost::any_cast<ValueType>(Get(key));
80 } catch( const boost::bad_any_cast & ) {
81 std::cerr << "Cannot cast property " << key << " to ";
82 std::cerr << typeid(ValueType).name() << std::endl;
83 return boost::any_cast<ValueType>(Get(key));
84 }
85 }
86
87 /// Converts a property from string to ValueType (if necessary)
88 template<typename ValueType>
89 void ConvertTo(const PropertyKey &key) {
90 PropertyValue val = Get(key);
91 if( val.type() != typeid(ValueType) ) {
92 assert( val.type() == typeid(std::string) );
93
94 std::stringstream ss;
95 ss << GetAs<std::string>(key);
96 ValueType result;
97 ss >> result;
98
99 Set(key, result);
100 }
101 }
102
103 /// Converts a property from string to ValueType (if necessary)
104 template<typename ValueType>
105 ValueType getStringAs(const PropertyKey &key) const {
106 PropertyValue val = Get(key);
107 if( val.type() == typeid(std::string) ) {
108 std::stringstream ss;
109 ss << GetAs<std::string>(key);
110 ValueType result;
111 ss >> result;
112 return result;
113 } else if( val.type() == typeid(ValueType) ) {
114 return boost::any_cast<ValueType>(val);
115 } else {
116 DAI_THROW(IMPOSSIBLE_TYPECAST);
117 return ValueType();
118 }
119 }
120
121 /// Converts a property from ValueType to string (if necessary)
122 template<typename ValueType>
123 PropertySet & setAsString(const PropertyKey &key, ValueType &val) {
124 if( val.type() == typeid(std::string) ) {
125 return Set(key, val);
126 } else {
127 std::stringstream ss (std::stringstream::out);
128 ss << val;
129 return Set(key, ss.str());
130 }
131 }
132
133 /// Shorthand for (temporarily) adding properties, e.g. PropertySet p()("method","BP")("verbose",1)("tol",1e-9)
134 PropertySet operator()(const PropertyKey &key, const PropertyValue &val) const { PropertySet copy = *this; return copy.Set(key,val); }
135
136 /// Check if a property with the given key exists
137 bool hasKey(const PropertyKey &key) const { PropertySet::const_iterator x = find(key); return (x != this->end()); }
138
139 // Friends
140 friend std::ostream& operator<< (std::ostream & os, const PropertySet & ps);
141 friend std::istream& operator>> (std::istream& is, PropertySet & ps);
142 };
143
144
145 } // end of namespace dai
146
147
148 #endif