GraphMLWriter.hpp 20.9 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
	int n_attr = 0;

incardon's avatar
incardon committed
65
66
67
	//! indicate if attributes_names is to destroy
	bool to_destroy = false;

incardon's avatar
incardon committed
68
69
70
71
72
	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
	 * \param v_prop std::string that is filled with the graph properties in the GraphML format
73
	 * \param a_name array with the names of the properties
incardon's avatar
incardon committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	 *
	 */
	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
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];
incardon's avatar
incardon committed
98
		to_destroy = true;
incardon's avatar
incardon committed
99
100
101

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

incardon's avatar
incardon committed
104
	//! destructor
incardon's avatar
incardon committed
105
106
107
108
109
	~vertex_prop()
	{
		if (to_destroy == true)
		{delete [] attributes_names;}
	}
incardon's avatar
incardon committed
110

111
112
113
114
115
	/*! It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
116
117
118
119
120
121
122
    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
123
124
    		if (attributes_names[cnt] == "x" || attributes_names[cnt] == "y"
    			|| attributes_names[cnt] == "z" || attributes_names[cnt] == "shape" )
incardon's avatar
incardon committed
125
126
127
128
    		{cnt++; return ;}

    		// Create a property string based on the type of the property
    		if (typeid(T) == typeid(float))
incardon's avatar
incardon committed
129
    			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
130
    		else if (typeid(T) == typeid(double))
incardon's avatar
incardon committed
131
    			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
132
    		else if (typeid(T) == typeid(int))
incardon's avatar
incardon committed
133
    			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
134
    		else if (typeid(T) == typeid(long int))
incardon's avatar
incardon committed
135
    			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
136
    		else if (typeid(T) == typeid(bool))
incardon's avatar
incardon committed
137
    			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
138
    		else if (typeid(T) == typeid(std::string))
incardon's avatar
incardon committed
139
    			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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
    	}

    	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
{
158
	//! Vertex object container
incardon's avatar
incardon committed
159
160
	const typename G::V_container & vo;

161
	//! Properties counter
incardon's avatar
incardon committed
162
163
	int cnt = 0;

164
	//! vertex node string
incardon's avatar
incardon committed
165
166
	std::string & v_node;

167
	//! Attribute names
incardon's avatar
incardon committed
168
169
	std::string * attributes_names;

170
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
171
172
	int n_attr = 0;

incardon's avatar
incardon committed
173
174
175
	//! indicate if attributes_names is to destroy
	bool to_destroy = false;

incardon's avatar
incardon committed
176
177
178
179
180
181
	/*! \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<...>
182
	 * \param a_name stub SFINAE, it basically check if G has properties names defined, if yes this
incardon's avatar
incardon committed
183
184
185
	 *        constructor is selected over the other one
	 *
	 */
186
	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
187
188
189
190
191
192
	: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);
	};

193
194
195
196
197
198
199
200
201
202
203
204
#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
205
206
207
208
	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
incardon's avatar
incardon committed
209
	 * \param v_node std::string that is filled with the graph properties in the GraphML format
incardon's avatar
incardon committed
210
211
212
	 * \param n_obj object container to access its properties for example encapc<...>
	 *
	 */
213
	inline vertex_node(std::string & v_node, const typename G::V_container & n_obj)
incardon's avatar
incardon committed
214
215
	:vo(n_obj),v_node(v_node),attributes_names(NULL)
	{
incardon's avatar
incardon committed
216
217
218
219
220
		// 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];
incardon's avatar
incardon committed
221
		to_destroy = true;
incardon's avatar
incardon committed
222
223
224

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

227
228
	inline ~vertex_node()
	{
incardon's avatar
incardon committed
229
230
		if (to_destroy == true)
		{delete [] attributes_names;}
231
232
	}

233
234
235
236
237
238
239
240
241
242
243
244
#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
245
246
	/*! \brief Create a new node
	 *
247
	 * \param v_c id of the node
incardon's avatar
incardon committed
248
249
	 *
	 */
incardon's avatar
incardon committed
250
	void new_node(size_t v_c)
incardon's avatar
incardon committed
251
252
	{
		// start a new node
incardon's avatar
incardon committed
253
		v_node += "<node id=\"n"+ std::to_string(v_c) + "\">\n";
incardon's avatar
incardon committed
254
255
256
257
258
259
260
261
262
263
264
265
266

		// reset the counter properties
		cnt = 0;
	}

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

270
271
272
273
274
	/*! \brief It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
275
276
277
278
279
280
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (T::value < n_attr)
    	{
incardon's avatar
incardon committed
281
282
283
284
285
286
287
288
289
290
291
292
293
    		// 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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    	}

    	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
{
312
	//! Properties counter
incardon's avatar
incardon committed
313
314
	int cnt = 0;

315
	//! edge properties
incardon's avatar
incardon committed
316
317
	std::string & e_prop;

318
	//! Attribute names
incardon's avatar
incardon committed
319
320
	std::string * attributes_names;

321
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
322
323
	int n_attr = 0;

incardon's avatar
incardon committed
324
325
326
	//! indicate if attributes_names is to destroy
	bool to_destroy = false;

incardon's avatar
incardon committed
327
328
329
330
331
	/*! \brief Constructor
	 *
	 * Create an edge properties list
	 *
	 * \param e_prop std::string that is filled with the graph properties in the GraphML format
332
	 * \param a_name stub SFINAE, it basically check if G::E_type has properties names defined, if yes this
incardon's avatar
incardon committed
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
	 *        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
350
	edge_prop(std::string & e_prop)
incardon's avatar
incardon committed
351
352
	:e_prop(e_prop),attributes_names(NULL)
	{
incardon's avatar
incardon committed
353
354
355
356
357
		// 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];
incardon's avatar
incardon committed
358
		to_destroy = true;
incardon's avatar
incardon committed
359
360
361

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

incardon's avatar
incardon committed
364
365
366
367
368
	inline ~edge_prop()
	{
		if (to_destroy == true)
		{delete [] attributes_names;}
	}
incardon's avatar
incardon committed
369

370
371
372
373
374
	/*! \brief It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
375
376
377
378
379
380
381
382
    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
383
    			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
384
    		else if (typeid(T) == typeid(double))
incardon's avatar
incardon committed
385
    			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
386
    		else if (typeid(T) == typeid(int))
incardon's avatar
incardon committed
387
    			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
388
    		else if (typeid(T) == typeid(long int))
incardon's avatar
incardon committed
389
    			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
390
    		else if (typeid(T) == typeid(bool))
incardon's avatar
incardon committed
391
    			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
392
    		else if (typeid(T) == typeid(std::string))
incardon's avatar
incardon committed
393
    			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
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    	}

    	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
412
	//! Vertex object container
incardon's avatar
incardon committed
413
	typename G::E_container & vo;
incardon's avatar
incardon committed
414

incardon's avatar
incardon committed
415
	//! Properties counter
incardon's avatar
incardon committed
416
417
	int cnt = 0;

418
	//! edge node string
incardon's avatar
incardon committed
419
420
	std::string & e_node;

incardon's avatar
incardon committed
421
	//! Attribute names
incardon's avatar
incardon committed
422
423
	std::string * attributes_names;

incardon's avatar
incardon committed
424
	//! Number of attributes name defined into the vertex
incardon's avatar
incardon committed
425
426
	int n_attr = 0;

incardon's avatar
incardon committed
427
428
429
	//! indicate if attributes_names is to destroy
	bool to_destroy = false;

incardon's avatar
incardon committed
430
431
432
433
434
435
	/*! \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
436
	 * \param a_name attributes names
incardon's avatar
incardon committed
437
438
	 *
	 */
incardon's avatar
incardon committed
439
	edge_node(std::string & e_node, typename G::E_container & n_obj, typename G::E_type::attributes & a_name)
incardon's avatar
incardon committed
440
441
442
443
444
445
446
447
448
449
450
451
452
453
	: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
454
	edge_node(std::string & e_node, typename G::E_container & n_obj)
incardon's avatar
incardon committed
455
456
	:vo(n_obj),e_node(e_node),attributes_names(NULL)
	{
incardon's avatar
incardon committed
457
458
459
460
461
		// 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];
incardon's avatar
incardon committed
462
		to_destroy = true;
incardon's avatar
incardon committed
463
464
465
466

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

incardon's avatar
incardon committed
467
468
	};

incardon's avatar
incardon committed
469
470
471
472
473
474
	inline ~edge_node()
	{
		if (to_destroy == true)
		{delete [] attributes_names;}
	}

incardon's avatar
incardon committed
475
476
	/*! \brief Create a new node
	 *
477
478
479
	 * \param v_c node number
	 * \param s source node id
	 * \param d destination node id
incardon's avatar
incardon committed
480
481
	 *
	 */
incardon's avatar
incardon committed
482
	void new_node(size_t v_c, size_t s, size_t d)
incardon's avatar
incardon committed
483
484
	{
		// start a new node
incardon's avatar
incardon committed
485
		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
486
487
488
489
490
491
492
493
494
495
496
497
498

		// reset the counter properties
		cnt = 0;
	}

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

502
503
504
505
506
	/*! It call the functor for each member
	 *
	 * \param t each member
	 *
	 */
incardon's avatar
incardon committed
507
508
509
510
511
512
    template<typename T>
    void operator()(T& t)
    {
    	//! Create an entry for the attribute
    	if (T::value < n_attr)
    	{
incardon's avatar
incardon committed
513
514
515
516
517
518
519
520
521
522
523
524
525
    		// 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
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
    	}

    	cnt++;
    }
};

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

template <typename Graph>
class GraphMLWriter
{
541
	//! Graph to write
incardon's avatar
incardon committed
542
543
544
545
546
	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
547
	 * and
incardon's avatar
incardon committed
548
549
550
551
552
553
554
555
	 * 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
556
		std::string v_out("");
incardon's avatar
incardon committed
557
558
559
560
561

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

		// Iterate through all the vertex and create the vertex list
incardon's avatar
incardon committed
562
		boost::mpl::for_each_ref< typename Graph::V_type::type >(vp);
incardon's avatar
incardon committed
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

		// 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
578
		std::string e_out;
incardon's avatar
incardon committed
579
580

		// create a vertex property functor
incardon's avatar
incardon committed
581
		edge_prop<Graph> ep(e_out);
incardon's avatar
incardon committed
582
583

		// Iterate through all the vertex and create the vertex list
incardon's avatar
incardon committed
584
		boost::mpl::for_each_ref< typename Graph::E_type::type >(ep);
incardon's avatar
incardon committed
585
586

		// return the edge properties string
incardon's avatar
incardon committed
587
		return e_out;
incardon's avatar
incardon committed
588
589
	}

590
591
592
593
594
	/*! \brief Get the string containing the set of vertices
	 *
	 * \return the set of vertices as string
	 *
	 */
incardon's avatar
incardon committed
595
596
	std::string get_vertex_list()
	{
incardon's avatar
incardon committed
597
598
599
		// node counter
		size_t nc = 0;

incardon's avatar
incardon committed
600
601
602
603
604
605
606
607
608
		//! 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())
		{
609
610
			auto v = g.vertex(it.get());

incardon's avatar
incardon committed
611
			// create a vertex list functor
612
			vertex_node<Graph> vn(v_out,v);
incardon's avatar
incardon committed
613

incardon's avatar
incardon committed
614
615
616
			// create new node
			vn.new_node(nc);

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

incardon's avatar
incardon committed
620
621
622
623
			// end node
			vn.end_node();

			// increment the iterator and counter
incardon's avatar
incardon committed
624
			++it;
incardon's avatar
incardon committed
625
			nc++;
incardon's avatar
incardon committed
626
627
628
629
630
631
		}

		// return the vertex list
		return v_out;
	}

632
633
634
635
636
	/*! \brief return the edge list as a string
	 *
	 * \return the edge list as string
	 *
	 */
incardon's avatar
incardon committed
637
638
	std::string get_edge_list()
	{
incardon's avatar
incardon committed
639
640
641
		// node counter
		size_t nc = 0;

incardon's avatar
incardon committed
642
		//! edge node output string
incardon's avatar
incardon committed
643
		std::string e_out;
incardon's avatar
incardon committed
644
645
646
647
648
649
650

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

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

incardon's avatar
incardon committed
654
			// create an edge list functor
incardon's avatar
incardon committed
655
656
657
658
			edge_node<Graph> en(e_out,obj);

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

incardon's avatar
incardon committed
660
			// Iterate through all the edges and create the edge list
incardon's avatar
incardon committed
661
			boost::mpl::for_each_ref< boost::mpl::range_c<int,0,Graph::E_type::max_prop> >(en);
incardon's avatar
incardon committed
662

incardon's avatar
incardon committed
663
664
665
			// end new node
			en.end_node();

incardon's avatar
incardon committed
666
667
			// increment the operator
			++it;
incardon's avatar
incardon committed
668
			nc++;
incardon's avatar
incardon committed
669
670
671
		}

		// return the edge list
incardon's avatar
incardon committed
672
		return e_out;
incardon's avatar
incardon committed
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
	}

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
714
715
716
717
718
		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
719
720

		// Graph header to define an header
incardon's avatar
incardon committed
721
		graph_header = "<graph id=\"" + graph_name + "\" edgedefault=\"undirected\">\n";
incardon's avatar
incardon committed
722
		// Graph header end
incardon's avatar
incardon committed
723
		graph_header_end =  "</graph>\n";
incardon's avatar
incardon committed
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

		// 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
745
		if (ofs.is_open() == false)
incardon's avatar
incardon committed
746
747
748
749
750
		{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
751
752
753
754
		// Close the file

		ofs.close();

incardon's avatar
incardon committed
755
756
757
758
759
760
		// Completed succefully
		return true;
	}
};

#endif