File indexing completed on 2025-01-18 09:37:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_GRAPH_GRAPHML_HPP
0013 #define BOOST_GRAPH_GRAPHML_HPP
0014
0015 #include <boost/config.hpp>
0016 #include <boost/lexical_cast.hpp>
0017 #include <boost/any.hpp>
0018 #include <boost/type_traits/is_convertible.hpp>
0019 #include <boost/graph/dll_import_export.hpp>
0020 #include <boost/graph/graphviz.hpp> // for exceptions
0021 #include <boost/mpl/bool.hpp>
0022 #include <boost/mpl/vector.hpp>
0023 #include <boost/mpl/find.hpp>
0024 #include <boost/mpl/for_each.hpp>
0025 #include <boost/property_tree/detail/xml_parser_utils.hpp>
0026 #include <boost/throw_exception.hpp>
0027 #include <exception>
0028 #include <sstream>
0029 #include <typeinfo>
0030
0031 namespace boost
0032 {
0033
0034
0035
0036
0037 struct BOOST_SYMBOL_VISIBLE parse_error : public graph_exception
0038 {
0039 parse_error(const std::string& err)
0040 {
0041 error = err;
0042 statement = "parse error: " + error;
0043 }
0044 ~parse_error() throw() BOOST_OVERRIDE {}
0045 const char* what() const throw() BOOST_OVERRIDE { return statement.c_str(); }
0046 std::string statement;
0047 std::string error;
0048 };
0049
0050 class mutate_graph
0051 {
0052 public:
0053 virtual ~mutate_graph() {}
0054 virtual bool is_directed() const = 0;
0055
0056 virtual boost::any do_add_vertex() = 0;
0057 virtual std::pair< boost::any, bool > do_add_edge(
0058 boost::any source, boost::any target)
0059 = 0;
0060
0061 virtual void set_graph_property(const std::string& name,
0062 const std::string& value, const std::string& value_type)
0063 = 0;
0064
0065 virtual void set_vertex_property(const std::string& name, boost::any vertex,
0066 const std::string& value, const std::string& value_type)
0067 = 0;
0068
0069 virtual void set_edge_property(const std::string& name, boost::any edge,
0070 const std::string& value, const std::string& value_type)
0071 = 0;
0072 };
0073
0074 template < typename MutableGraph > class mutate_graph_impl : public mutate_graph
0075 {
0076 typedef typename graph_traits< MutableGraph >::vertex_descriptor
0077 vertex_descriptor;
0078 typedef
0079 typename graph_traits< MutableGraph >::edge_descriptor edge_descriptor;
0080
0081 public:
0082 mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
0083 : m_g(g), m_dp(dp)
0084 {
0085 }
0086
0087 bool is_directed() const BOOST_OVERRIDE
0088 {
0089 return is_convertible<
0090 typename graph_traits< MutableGraph >::directed_category,
0091 directed_tag >::value;
0092 }
0093
0094 any do_add_vertex() BOOST_OVERRIDE { return any(add_vertex(m_g)); }
0095
0096 std::pair< any, bool > do_add_edge(any source, any target) BOOST_OVERRIDE
0097 {
0098 std::pair< edge_descriptor, bool > retval
0099 = add_edge(any_cast< vertex_descriptor >(source),
0100 any_cast< vertex_descriptor >(target), m_g);
0101 return std::make_pair(any(retval.first), retval.second);
0102 }
0103
0104 void set_graph_property(const std::string& name,
0105 const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0106 {
0107 bool type_found = false;
0108 try
0109 {
0110 mpl::for_each< value_types >(
0111 put_property< MutableGraph*, value_types >(name, m_dp, &m_g,
0112 value, value_type, m_type_names, type_found));
0113 }
0114 catch (const bad_lexical_cast&)
0115 {
0116 BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0117 + "\" for key " + name + " of type " + value_type));
0118 }
0119 if (!type_found)
0120 {
0121 BOOST_THROW_EXCEPTION(parse_error(
0122 "unrecognized type \"" + value_type + "\" for key " + name));
0123 }
0124 }
0125
0126 void set_vertex_property(const std::string& name, any vertex,
0127 const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0128 {
0129 bool type_found = false;
0130 try
0131 {
0132 mpl::for_each< value_types >(
0133 put_property< vertex_descriptor, value_types >(name, m_dp,
0134 any_cast< vertex_descriptor >(vertex), value, value_type,
0135 m_type_names, type_found));
0136 }
0137 catch (const bad_lexical_cast&)
0138 {
0139 BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0140 + "\" for key " + name + " of type " + value_type));
0141 }
0142 if (!type_found)
0143 {
0144 BOOST_THROW_EXCEPTION(parse_error(
0145 "unrecognized type \"" + value_type + "\" for key " + name));
0146 }
0147 }
0148
0149 void set_edge_property(const std::string& name, any edge,
0150 const std::string& value, const std::string& value_type) BOOST_OVERRIDE
0151 {
0152 bool type_found = false;
0153 try
0154 {
0155 mpl::for_each< value_types >(
0156 put_property< edge_descriptor, value_types >(name, m_dp,
0157 any_cast< edge_descriptor >(edge), value, value_type,
0158 m_type_names, type_found));
0159 }
0160 catch (const bad_lexical_cast&)
0161 {
0162 BOOST_THROW_EXCEPTION(parse_error("invalid value \"" + value
0163 + "\" for key " + name + " of type " + value_type));
0164 }
0165 if (!type_found)
0166 {
0167 BOOST_THROW_EXCEPTION(parse_error(
0168 "unrecognized type \"" + value_type + "\" for key " + name));
0169 }
0170 }
0171
0172 template < typename Key, typename ValueVector > class put_property
0173 {
0174 public:
0175 put_property(const std::string& name, dynamic_properties& dp,
0176 const Key& key, const std::string& value,
0177 const std::string& value_type, const char** type_names,
0178 bool& type_found)
0179 : m_name(name)
0180 , m_dp(dp)
0181 , m_key(key)
0182 , m_value(value)
0183 , m_value_type(value_type)
0184 , m_type_names(type_names)
0185 , m_type_found(type_found)
0186 {
0187 }
0188 template < class Value > void operator()(Value)
0189 {
0190 if (m_value_type
0191 == m_type_names[mpl::find< ValueVector,
0192 Value >::type::pos::value])
0193 {
0194 put(m_name, m_dp, m_key, lexical_cast< Value >(m_value));
0195 m_type_found = true;
0196 }
0197 }
0198
0199 private:
0200 const std::string& m_name;
0201 dynamic_properties& m_dp;
0202 const Key& m_key;
0203 const std::string& m_value;
0204 const std::string& m_value_type;
0205 const char** m_type_names;
0206 bool& m_type_found;
0207 };
0208
0209 protected:
0210 MutableGraph& m_g;
0211 dynamic_properties& m_dp;
0212 typedef mpl::vector< bool, int, long, float, double, std::string >
0213 value_types;
0214 static const char* m_type_names[];
0215 };
0216
0217 template < typename MutableGraph >
0218 const char* mutate_graph_impl< MutableGraph >::m_type_names[]
0219 = { "boolean", "int", "long", "float", "double", "string" };
0220
0221 void BOOST_GRAPH_DECL read_graphml(
0222 std::istream& in, mutate_graph& g, size_t desired_idx);
0223
0224 template < typename MutableGraph >
0225 void read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp,
0226 size_t desired_idx = 0)
0227 {
0228 mutate_graph_impl< MutableGraph > mg(g, dp);
0229 read_graphml(in, mg, desired_idx);
0230 }
0231
0232 template < typename Types > class get_type_name
0233 {
0234 public:
0235 get_type_name(const std::type_info& type, const char** type_names,
0236 std::string& type_name)
0237 : m_type(type), m_type_names(type_names), m_type_name(type_name)
0238 {
0239 }
0240 template < typename Type > void operator()(Type)
0241 {
0242 if (typeid(Type) == m_type)
0243 m_type_name
0244 = m_type_names[mpl::find< Types, Type >::type::pos::value];
0245 }
0246
0247 private:
0248 const std::type_info& m_type;
0249 const char** m_type_names;
0250 std::string& m_type_name;
0251 };
0252
0253 template < typename Graph, typename VertexIndexMap >
0254 void write_graphml(std::ostream& out, const Graph& g,
0255 VertexIndexMap vertex_index, const dynamic_properties& dp,
0256 bool ordered_vertices = false)
0257 {
0258 typedef typename graph_traits< Graph >::directed_category directed_category;
0259 typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
0260 typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
0261
0262 using boost::property_tree::xml_parser::encode_char_entities;
0263
0264 BOOST_STATIC_CONSTANT(bool,
0265 graph_is_directed
0266 = (is_convertible< directed_category*, directed_tag* >::value));
0267
0268 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0269 << "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" "
0270 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
0271 "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns "
0272 "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
0273
0274 typedef mpl::vector< bool, short, unsigned short, int, unsigned int, long,
0275 unsigned long, long long, unsigned long long, float, double,
0276 long double, std::string >
0277 value_types;
0278 const char* type_names[] = { "boolean", "int", "int", "int", "int", "long",
0279 "long", "long", "long", "float", "double", "double", "string" };
0280 std::map< std::string, std::string > graph_key_ids;
0281 std::map< std::string, std::string > vertex_key_ids;
0282 std::map< std::string, std::string > edge_key_ids;
0283 int key_count = 0;
0284
0285
0286 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
0287 {
0288 std::string key_id = "key" + lexical_cast< std::string >(key_count++);
0289 if (i->second->key() == typeid(Graph*))
0290 graph_key_ids[i->first] = key_id;
0291 else if (i->second->key() == typeid(vertex_descriptor))
0292 vertex_key_ids[i->first] = key_id;
0293 else if (i->second->key() == typeid(edge_descriptor))
0294 edge_key_ids[i->first] = key_id;
0295 else
0296 continue;
0297 std::string type_name = "string";
0298 mpl::for_each< value_types >(get_type_name< value_types >(
0299 i->second->value(), type_names, type_name));
0300 out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
0301 << (i->second->key() == typeid(Graph*)
0302 ? "graph"
0303 : (i->second->key() == typeid(vertex_descriptor)
0304 ? "node"
0305 : "edge"))
0306 << "\""
0307 << " attr.name=\"" << i->first << "\""
0308 << " attr.type=\"" << type_name << "\""
0309 << " />\n";
0310 }
0311
0312 out << " <graph id=\"G\" edgedefault=\""
0313 << (graph_is_directed ? "directed" : "undirected") << "\""
0314 << " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free")
0315 << "\""
0316 << " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
0317
0318
0319 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
0320 {
0321 if (i->second->key() == typeid(Graph*))
0322 {
0323
0324
0325 out << " <data key=\"" << graph_key_ids[i->first] << "\">"
0326 << encode_char_entities(
0327 i->second->get_string(const_cast< Graph* >(&g)))
0328 << "</data>\n";
0329 }
0330 }
0331
0332 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0333 vertex_iterator v, v_end;
0334 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
0335 {
0336 out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
0337
0338 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
0339 ++i)
0340 {
0341 if (i->second->key() == typeid(vertex_descriptor))
0342 {
0343 out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
0344 << encode_char_entities(i->second->get_string(*v))
0345 << "</data>\n";
0346 }
0347 }
0348 out << " </node>\n";
0349 }
0350
0351 typedef typename graph_traits< Graph >::edge_iterator edge_iterator;
0352 edge_iterator e, e_end;
0353 typename graph_traits< Graph >::edges_size_type edge_count = 0;
0354 for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
0355 {
0356 out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
0357 << get(vertex_index, source(*e, g)) << "\" target=\"n"
0358 << get(vertex_index, target(*e, g)) << "\">\n";
0359
0360
0361 for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
0362 ++i)
0363 {
0364 if (i->second->key() == typeid(edge_descriptor))
0365 {
0366 out << " <data key=\"" << edge_key_ids[i->first] << "\">"
0367 << encode_char_entities(i->second->get_string(*e))
0368 << "</data>\n";
0369 }
0370 }
0371 out << " </edge>\n";
0372 }
0373
0374 out << " </graph>\n"
0375 << "</graphml>\n";
0376 }
0377
0378 template < typename Graph >
0379 void write_graphml(std::ostream& out, const Graph& g,
0380 const dynamic_properties& dp, bool ordered_vertices = false)
0381 {
0382 write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
0383 }
0384
0385 }
0386
0387 #endif