GraphMLWriter.hpp 20.2 KB
Newer Older
incardon's avatar
incardon committed
1 2 3
#ifndef GRAPHML_WRITER_HPP
#define GRAPHML_WRITER_HPP

incardon's avatar
incardon committed
4
#include "Graph/map_graph.hpp"
incardon's avatar
incardon committed
5 6
#include <iostream>
#include <fstream>
incardon's avatar
incardon committed
7
#include "util/common.hpp"
incardon's avatar
incardon committed
8

incardon's avatar
incardon committed
9

incardon's avatar
incardon committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*! \brief Create properties name starting from a type T
 *
 * if T has defined some properties name that name are used otherwise
 * default name are created
 *
 * \tparam T vertex type
 *
 */

template <typename T>
void create_prop(std::string * str)
{
	// if T has attributes defined
	if (has_attributes<T>::value )
incardon's avatar
incardon committed
24
	{
incardon's avatar
incardon committed
25
		// Create properties names based on the attributes name defined
incardon's avatar
incardon committed
26
		for (size_t i = 0 ; i < T::max_prop ; i++)
incardon's avatar
incardon committed
27 28 29 30 31 32 33
		{
			str[i] = std::string(T::attributes::name[i]);
		}
	}
	else
	{
		// Create default properties name
incardon's avatar
incardon committed
34
		for (size_t i = 0 ; i < T::max_prop ; i++)
incardon's avatar
incardon committed
35 36 37
		{
			str[i] = "attr" + std::to_string(i);
		}
incardon's avatar
incardon committed
38 39 40
	}
}

incardon's avatar
incardon committed
41 42 43 44 45 46 47 48 49 50 51 52
/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the vertex
 * properties
 *
 */

template<typename G>
struct vertex_prop
{
53
	//! Properties counter
incardon's avatar
incardon committed
54 55
	int cnt = 0;

56
	//! vertex properties
incardon's avatar
incardon committed
57 58
	std::string & v_prop;

59
	//! Attribute names
incardon's avatar
incardon committed
60 61
	std::string * attributes_names;

62
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
63 64 65 66 67 68 69
	int n_attr = 0;

	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
	 * \param v_prop std::string that is filled with the graph properties in the GraphML format
70
	 * \param a_name array with the names of the properties
incardon's avatar
incardon committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
	 *
	 */
	vertex_prop(std::string & v_prop, typename G::V_type::attributes & a_name)
	:v_prop(v_prop),attributes_names(a_name.name)
	{
		// Calculate the number of attributes name
		n_attr = sizeof(a_name.name)/sizeof(std::string);
	};

	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
	 * \param v_prop std::string that is filled with the graph properties in the GraphML format
	 *
	 */
	vertex_prop(std::string & v_prop)
	:v_prop(v_prop),attributes_names(NULL)
	{
incardon's avatar
incardon committed
90 91 92 93 94 95 96 97
		// Calculate the number of attributes
		n_attr = G::V_type::max_prop;

		// Create default property names
		attributes_names = new std::string[G::V_type::max_prop];

		// Create default property names
		create_prop<typename G::V_type>(attributes_names);
incardon's avatar
incardon committed
98 99
	};

100 101 102 103 104
	/*! It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
105 106 107 108 109 110 111
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (cnt < n_attr)
    	{
    		// if it is a yFile extension property name, does not process it
incardon's avatar
incardon committed
112 113
    		if (attributes_names[cnt] == "x" || attributes_names[cnt] == "y"
    			|| attributes_names[cnt] == "z" || attributes_names[cnt] == "shape" )
incardon's avatar
incardon committed
114 115 116 117
    		{cnt++; return ;}

    		// Create a property string based on the type of the property
    		if (typeid(T) == typeid(float))
incardon's avatar
incardon committed
118
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"float\"/>\n";
incardon's avatar
incardon committed
119
    		else if (typeid(T) == typeid(double))
incardon's avatar
incardon committed
120
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"double\"/>\n";
incardon's avatar
incardon committed
121
    		else if (typeid(T) == typeid(int))
incardon's avatar
incardon committed
122
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"int\"/>\n";
incardon's avatar
incardon committed
123
    		else if (typeid(T) == typeid(long int))
incardon's avatar
incardon committed
124
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"long\"/>\n";
incardon's avatar
incardon committed
125
    		else if (typeid(T) == typeid(bool))
incardon's avatar
incardon committed
126
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"boolean\"/>\n";
incardon's avatar
incardon committed
127
    		else if (typeid(T) == typeid(std::string))
incardon's avatar
incardon committed
128
    			v_prop += "<key id=\"vk" + std::to_string(cnt) + "\" for=\"node\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"string\"/>\n";
incardon's avatar
incardon committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    	}

    	cnt++;
    }
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the vertex
 * properties
 *
 */

template<typename G>
struct vertex_node
{
147
	//! Vertex object container
incardon's avatar
incardon committed
148 149
	const typename G::V_container & vo;

150
	//! Properties counter
incardon's avatar
incardon committed
151 152
	int cnt = 0;

153
	//! vertex node string
incardon's avatar
incardon committed
154 155
	std::string & v_node;

156
	//! Attribute names
incardon's avatar
incardon committed
157 158
	std::string * attributes_names;

159
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
160 161 162 163 164 165 166 167
	int n_attr = 0;

	/*! \brief Constructor
	 *
	 * Create a vertex node
	 *
	 * \param v_node std::string that is filled with the graph node definition in the GraphML format
	 * \param n_obj object container to access its properties for example encapc<...>
168
	 * \param a_name stub SFINAE, it basically check if G has properties names defined, if yes this
incardon's avatar
incardon committed
169 170 171
	 *        constructor is selected over the other one
	 *
	 */
172
	inline vertex_node(std::string & v_node, const typename G::V_container & n_obj, typename G::V_type::attributes & a_name)
incardon's avatar
incardon committed
173 174 175 176 177 178
	:vo(n_obj),v_node(v_node),attributes_names(a_name.name)
	{
		// Calculate the number of attributes name
		n_attr = sizeof(a_name.name)/sizeof(std::string);
	};

179 180 181 182 183 184 185 186 187 188 189 190
#ifdef DEBUG
	/*! \brief Constructor
	 *
	 * Calling this constructor produce an error. This class store the reference of the object,
	 * this mean that the object passed must not be a temporal object
	 *
	 */
	inline vertex_node(std::string & v_node, const typename G::V_container && n_obj, typename G::V_type::attributes & a_name)
	:vo(n_obj),v_node(v_node),attributes_names(a_name.name)
	{std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object\n";};
#endif

incardon's avatar
incardon committed
191 192 193 194
	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
incardon's avatar
incardon committed
195
	 * \param v_node std::string that is filled with the graph properties in the GraphML format
incardon's avatar
incardon committed
196 197 198
	 * \param n_obj object container to access its properties for example encapc<...>
	 *
	 */
199
	inline vertex_node(std::string & v_node, const typename G::V_container & n_obj)
incardon's avatar
incardon committed
200 201
	:vo(n_obj),v_node(v_node),attributes_names(NULL)
	{
incardon's avatar
incardon committed
202 203 204 205 206 207 208 209
		// Calculate the number of attributes
		n_attr = G::V_type::max_prop;

		// Create default property names
		attributes_names = new std::string[G::V_type::max_prop];

		// Create default property names
		create_prop<typename G::V_type>(attributes_names);
incardon's avatar
incardon committed
210 211
	};

212 213 214 215 216
	inline ~vertex_node()
	{
		delete [] attributes_names;
	}

217 218 219 220 221 222 223 224 225 226 227 228
#ifdef DEBUG
	/*! \brief Constructor
	 *
	 * Calling this constructor produce an error. This class store the reference of the object,
	 * this mean that the object passed must not be a temporal object
	 *
	 */
	inline vertex_node(std::string & v_node, const typename G::V_container && n_obj)
	:vo(n_obj),v_node(v_node),attributes_names(NULL)
	{std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object\n";};
#endif

incardon's avatar
incardon committed
229 230
	/*! \brief Create a new node
	 *
231
	 * \param v_c id of the node
incardon's avatar
incardon committed
232 233
	 *
	 */
incardon's avatar
incardon committed
234
	void new_node(size_t v_c)
incardon's avatar
incardon committed
235 236
	{
		// start a new node
incardon's avatar
incardon committed
237
		v_node += "<node id=\"n"+ std::to_string(v_c) + "\">\n";
incardon's avatar
incardon committed
238 239 240 241 242 243 244 245 246 247 248 249 250

		// reset the counter properties
		cnt = 0;
	}

	/*! \brief Close a node
	 *
	 * Close a node
	 *
	 */
	void end_node()
	{
		// close a node
incardon's avatar
incardon committed
251
		v_node += "</node>\n";
incardon's avatar
incardon committed
252 253
	}

254 255 256 257 258
	/*! \brief It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
259 260 261 262 263 264
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (T::value < n_attr)
    	{
incardon's avatar
incardon committed
265 266 267 268 269 270 271 272 273 274 275 276 277
    		// Create a property string based on the type of the property
    		if (typeid(decltype(vo.template get<T::value>())) == typeid(float))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(double))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(int))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(long int))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(bool))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(std::string))
    			v_node += "  <data key=\"vk" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
incardon's avatar
incardon committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    	}

    	cnt++;
    }
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the edge
 * properties
 *
 */

template<typename G>
struct edge_prop
{
296
	//! Properties counter
incardon's avatar
incardon committed
297 298
	int cnt = 0;

299
	//! edge properties
incardon's avatar
incardon committed
300 301
	std::string & e_prop;

302
	//! Attribute names
incardon's avatar
incardon committed
303 304
	std::string * attributes_names;

305
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
306 307 308 309 310 311 312
	int n_attr = 0;

	/*! \brief Constructor
	 *
	 * Create an edge properties list
	 *
	 * \param e_prop std::string that is filled with the graph properties in the GraphML format
313
	 * \param a_name stub SFINAE, it basically check if G::E_type has properties names defined, if yes this
incardon's avatar
incardon committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
	 *        constructor is selected over the other one
	 *
	 */
	edge_prop(std::string & e_prop, typename G::E_type::attributes & a_name)
	:e_prop(e_prop),attributes_names(a_name.name)
	{
		// Calculate the number of attributes name
		n_attr = sizeof(a_name.name)/sizeof(std::string);
	};

	/*! \brief Constructor
	 *
	 * Create an edge properties list
	 *
	 * \param e_prop std::string that is filled with the graph properties in the GraphML format
	 *
	 */
incardon's avatar
incardon committed
331
	edge_prop(std::string & e_prop)
incardon's avatar
incardon committed
332 333
	:e_prop(e_prop),attributes_names(NULL)
	{
incardon's avatar
incardon committed
334 335 336 337 338 339 340 341
		// Calculate the number of attributes
		n_attr = G::E_type::max_prop;

		// Create default property names
		attributes_names = new std::string[G::E_type::max_prop];

		// Create default property names
		create_prop<typename G::E_type>(attributes_names);
incardon's avatar
incardon committed
342 343
	};

344 345 346 347 348
	/*! \brief It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
349 350 351 352 353 354 355 356
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (cnt < n_attr)
    	{
    		// Create a property string based on the type of the property
    		if (typeid(T) == typeid(float))
incardon's avatar
incardon committed
357
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"float\"/>\n";
incardon's avatar
incardon committed
358
    		else if (typeid(T) == typeid(double))
incardon's avatar
incardon committed
359
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"double\"/>\n";
incardon's avatar
incardon committed
360
    		else if (typeid(T) == typeid(int))
incardon's avatar
incardon committed
361
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"int\"/>\n";
incardon's avatar
incardon committed
362
    		else if (typeid(T) == typeid(long int))
incardon's avatar
incardon committed
363
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"long\"/>\n";
incardon's avatar
incardon committed
364
    		else if (typeid(T) == typeid(bool))
incardon's avatar
incardon committed
365
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"boolean\"/>\n";
incardon's avatar
incardon committed
366
    		else if (typeid(T) == typeid(std::string))
incardon's avatar
incardon committed
367
    			e_prop += "<key id=\"ek" + std::to_string(cnt) + "\" for=\"edge\" attr.name=\"" + attributes_names[cnt] + "\" attr.type=\"string\"/>\n";
incardon's avatar
incardon committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    	}

    	cnt++;
    }
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the edge
 * properties
 *
 */

template<typename G>
struct edge_node
{
incardon's avatar
incardon committed
386
	//! Vertex object container
incardon's avatar
incardon committed
387
	typename G::E_container & vo;
incardon's avatar
incardon committed
388

incardon's avatar
incardon committed
389
	//! Properties counter
incardon's avatar
incardon committed
390 391
	int cnt = 0;

392
	//! edge node string
incardon's avatar
incardon committed
393 394
	std::string & e_node;

incardon's avatar
incardon committed
395
	//! Attribute names
incardon's avatar
incardon committed
396 397
	std::string * attributes_names;

incardon's avatar
incardon committed
398
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
399 400 401 402 403 404 405 406
	int n_attr = 0;

	/*! \brief Constructor
	 *
	 * Create an edge node
	 *
	 * \param e_node std::string that is filled with the graph node definition in the GraphML format
	 * \param n_obj object container to access the object properties for example encapc<...>
incardon's avatar
incardon committed
407
	 * \param a_name attributes names
incardon's avatar
incardon committed
408 409
	 *
	 */
incardon's avatar
incardon committed
410
	edge_node(std::string & e_node, typename G::E_container & n_obj, typename G::E_type::attributes & a_name)
incardon's avatar
incardon committed
411 412 413 414 415 416 417 418 419 420 421 422 423 424
	:vo(n_obj),e_node(e_node),attributes_names(a_name.name)
	{
		// Calculate the number of attributes name
		n_attr = sizeof(a_name.name)/sizeof(std::string);
	};

	/*! \brief Constructor
	 *
	 * Create an edge node
	 *
	 * \param e_node std::string that is filled with the graph properties in the GraphML format
	 * \param n_obj object container to access the object properties for example encapc<...>
	 *
	 */
incardon's avatar
incardon committed
425
	edge_node(std::string & e_node, typename G::E_container & n_obj)
incardon's avatar
incardon committed
426 427
	:vo(n_obj),e_node(e_node),attributes_names(NULL)
	{
incardon's avatar
incardon committed
428 429 430 431 432 433 434 435 436
		// Calculate the number of attributes
		n_attr = G::E_type::max_prop;

		// Create a number of default properties name
		attributes_names  = new std::string[G::E_type::max_prop];

		// Create default property names
		create_prop<typename G::E_type>(attributes_names);

incardon's avatar
incardon committed
437 438 439 440
	};

	/*! \brief Create a new node
	 *
441 442 443
	 * \param v_c node number
	 * \param s source node id
	 * \param d destination node id
incardon's avatar
incardon committed
444 445
	 *
	 */
incardon's avatar
incardon committed
446
	void new_node(size_t v_c, size_t s, size_t d)
incardon's avatar
incardon committed
447 448
	{
		// start a new node
incardon's avatar
incardon committed
449
		e_node += "<edge id=\"e"+ std::to_string(v_c) + "\" source=\"n" + std::to_string(s) + "\" target=\"n" + std::to_string(d) + "\">\n";
incardon's avatar
incardon committed
450 451 452 453 454 455 456 457 458 459 460 461 462

		// reset the counter properties
		cnt = 0;
	}

	/*! \brief Close a node
	 *
	 * Close a node
	 *
	 */
	void end_node()
	{
		// close a node
incardon's avatar
incardon committed
463
		e_node += "</edge>\n";
incardon's avatar
incardon committed
464 465
	}

466 467 468 469 470
	/*! It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
471 472 473 474 475 476
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (T::value < n_attr)
    	{
incardon's avatar
incardon committed
477 478 479 480 481 482 483 484 485 486 487 488 489
    		// Create a property string based on the type of the property
    		if (typeid(decltype(vo.template get<T::value>())) == typeid(float))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(double))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(int))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(long int))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(bool))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
    		else if (typeid(decltype(vo.template get<T::value>())) == typeid(std::string))
    			e_node += "  <data key=\"ek" + std::to_string(cnt) + "\">" + std::to_string(vo.template get<T::value>()) + "</data>\n";
incardon's avatar
incardon committed
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    	}

    	cnt++;
    }
};

/*!
 *
 * From a Graphbasic structure it write a GraphML format file
 *
 */

template <typename Graph>
class GraphMLWriter
{
505
	//! Graph to write
incardon's avatar
incardon committed
506 507 508 509 510
	Graph & g;

	/*! \brief It get the vertex properties list
	 *
	 * It get the vertex properties list of the vertex defined as a GraphML header
incardon's avatar
incardon committed
511
	 * and
incardon's avatar
incardon committed
512 513 514 515 516 517 518 519
	 * define position and shape of the node
	 *
	 * \return a string that define the vertex properties in graphML format
	 *
	 */
	std::string get_vertex_properties_list()
	{
		//! vertex property output string
incardon's avatar
incardon committed
520
		std::string v_out("");
incardon's avatar
incardon committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541

		// create a vertex property functor
		vertex_prop<Graph> vp(v_out);

		// Iterate through all the vertex and create the vertex list
		boost::mpl::for_each< typename Graph::V_type::type >(vp);

		// return the vertex properties string
		return v_out;
	}

	/*! \brief It get the edge properties list
	 *
	 * It get the edge properties list of the edge defined as a GraphML header
	 *
	 * \return a string that define the edge properties in graphML format
	 *
	 */
	std::string get_edge_properties_list()
	{
		//! edge property output string
incardon's avatar
incardon committed
542
		std::string e_out;
incardon's avatar
incardon committed
543 544

		// create a vertex property functor
incardon's avatar
incardon committed
545
		edge_prop<Graph> ep(e_out);
incardon's avatar
incardon committed
546 547

		// Iterate through all the vertex and create the vertex list
incardon's avatar
incardon committed
548
		boost::mpl::for_each< typename Graph::E_type::type >(ep);
incardon's avatar
incardon committed
549 550

		// return the edge properties string
incardon's avatar
incardon committed
551
		return e_out;
incardon's avatar
incardon committed
552 553
	}

554 555 556 557 558
	/*! \brief Get the string containing the set of vertices
	 *
	 * \return the set of vertices as string
	 *
	 */
incardon's avatar
incardon committed
559 560
	std::string get_vertex_list()
	{
incardon's avatar
incardon committed
561 562 563
		// node counter
		size_t nc = 0;

incardon's avatar
incardon committed
564 565 566 567 568 569 570 571 572
		//! vertex node output string
		std::string v_out;

		//! Get a vertex iterator
		auto it = g.getVertexIterator();

		// if there is the next element
		while (it.isNext())
		{
573 574
			auto v = g.vertex(it.get());

incardon's avatar
incardon committed
575
			// create a vertex list functor
576
			vertex_node<Graph> vn(v_out,v);
incardon's avatar
incardon committed
577

incardon's avatar
incardon committed
578 579 580
			// create new node
			vn.new_node(nc);

incardon's avatar
incardon committed
581
			// Iterate through all the vertex and create the vertex list
582
			boost::mpl::for_each_ref< boost::mpl::range_c<int,0,Graph::V_type::max_prop> >(vn);
incardon's avatar
incardon committed
583

incardon's avatar
incardon committed
584 585 586 587
			// end node
			vn.end_node();

			// increment the iterator and counter
incardon's avatar
incardon committed
588
			++it;
incardon's avatar
incardon committed
589
			nc++;
incardon's avatar
incardon committed
590 591 592 593 594 595
		}

		// return the vertex list
		return v_out;
	}

596 597 598 599 600
	/*! \brief return the edge list as a string
	 *
	 * \return the edge list as string
	 *
	 */
incardon's avatar
incardon committed
601 602
	std::string get_edge_list()
	{
incardon's avatar
incardon committed
603 604 605
		// node counter
		size_t nc = 0;

incardon's avatar
incardon committed
606
		//! edge node output string
incardon's avatar
incardon committed
607
		std::string e_out;
incardon's avatar
incardon committed
608 609 610 611 612 613 614

		//! Get an edge iterator
		auto it = g.getEdgeIterator();

		// if there is the next element
		while (it.isNext())
		{
incardon's avatar
incardon committed
615 616 617
			// Get the edge object
			auto obj = g.edge(it.get());

incardon's avatar
incardon committed
618
			// create an edge list functor
incardon's avatar
incardon committed
619 620 621 622
			edge_node<Graph> en(e_out,obj);

			// create a new node
			en.new_node(nc,it.source(),it.target());
incardon's avatar
incardon committed
623

incardon's avatar
incardon committed
624 625
			// Iterate through all the edges and create the edge list
			boost::mpl::for_each< boost::mpl::range_c<int,0,Graph::E_type::max_prop> >(en);
incardon's avatar
incardon committed
626

incardon's avatar
incardon committed
627 628 629
			// end new node
			en.end_node();

incardon's avatar
incardon committed
630 631
			// increment the operator
			++it;
incardon's avatar
incardon committed
632
			nc++;
incardon's avatar
incardon committed
633 634 635
		}

		// return the edge list
incardon's avatar
incardon committed
636
		return e_out;
incardon's avatar
incardon committed
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
	}

public:

	/*!
	 *
	 * GraphMLWriter constructor, it take a graph and write a GraphML format
	 *
	 * \param g Graph to write
	 *
	 */
	GraphMLWriter(Graph & g)
	:g(g)
	{}

	/*! \brief It write a GraphML file from a graph
	 *
	 * \param file path where to write
	 * \param name of the graph
	 *
	 */
	bool write(std::string file, std::string graph_name="Graph")
	{
		// Header for the GraphML
		std::string gml_header;
		// Vertex list of the GraphML
		std::string vertex_list;
		// End for the GraphML
		std::string gml_header_end;
		// Graph header
		std::string graph_header;
		// Graph header end
		std::string graph_header_end;
		// Edge list of the GraphML
		std::string edge_list;
		// vertex properties header
		std::string vertex_prop_header;
		// edge properties header
		std::string edge_prop_header;

		// GraphML header
incardon's avatar
incardon committed
678 679 680 681 682
		gml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
		<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\n\
		    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\
		    xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\n\
		     http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
incardon's avatar
incardon committed
683 684

		// Graph header to define an header
incardon's avatar
incardon committed
685
		graph_header = "<graph id=\"" + graph_name + "\" edgedefault=\"undirected\">\n";
incardon's avatar
incardon committed
686
		// Graph header end
incardon's avatar
incardon committed
687
		graph_header_end =  "</graph>\n";
incardon's avatar
incardon committed
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708

		// Vertex properties header
		vertex_prop_header = get_vertex_properties_list();

		// Edge properties header
		edge_prop_header = get_edge_properties_list();

		// Get the node graph list
		vertex_list = get_vertex_list();

		// Get the edge graph list
		edge_list = get_edge_list();

		// Header end
		gml_header_end = "</graphml>";

		// write the file

		std::ofstream ofs(file);

		// Check if the file is open
incardon's avatar
incardon committed
709
		if (ofs.is_open() == false)
incardon's avatar
incardon committed
710 711 712 713 714
		{std::cerr << "Error cannot creare the graphML file: " + file;}

		ofs << gml_header << graph_header << vertex_prop_header << edge_prop_header <<
			   vertex_list << edge_list << graph_header_end << gml_header_end;

incardon's avatar
incardon committed
715 716 717 718
		// Close the file

		ofs.close();

incardon's avatar
incardon committed
719 720 721 722 723 724
		// Completed succefully
		return true;
	}
};

#endif