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