Line data Source code
1 : /* File: io_exporter.c; Copyright and License: see below */
2 :
3 : #include "io_exporter.h"
4 : #include "document/document_css_writer.h"
5 : #include "json/json_schema_writer.h"
6 : #include "u8stream/universal_file_output_stream.h"
7 : #include "u8stream/universal_output_stream.h"
8 : #include "xmi/xmi_writer_pass.h"
9 : #include "u8/u8_trace.h"
10 : #include "u8/u8_log.h"
11 : #include "io_gtk.h"
12 : #include <cairo-svg.h>
13 : #include <cairo-pdf.h>
14 : #include <cairo-ps.h>
15 : #include <stdbool.h>
16 : #include <assert.h>
17 :
18 : enum io_exporter_max_enum {
19 : IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH = 16,
20 : };
21 :
22 2 : void io_exporter_init ( io_exporter_t *this_,
23 : data_database_reader_t *db_reader )
24 : {
25 2 : U8_TRACE_BEGIN();
26 2 : assert( NULL != db_reader );
27 :
28 2 : (*this_).db_reader = db_reader;
29 :
30 2 : (*this_).temp_filename = utf8stringbuf_new( (*this_).temp_filename_buf, sizeof((*this_).temp_filename_buf) );
31 2 : utf8stringbuf_clear( &((*this_).temp_filename) );
32 :
33 2 : U8_TRACE_END();
34 2 : }
35 :
36 2 : void io_exporter_destroy( io_exporter_t *this_ )
37 : {
38 2 : U8_TRACE_BEGIN();
39 :
40 2 : (*this_).db_reader = NULL;
41 :
42 2 : U8_TRACE_END();
43 2 : }
44 :
45 0 : u8_error_t io_exporter_export_files( io_exporter_t *this_,
46 : io_file_format_t export_type,
47 : const char *target_folder,
48 : const char *document_file_path,
49 : data_stat_t *io_export_stat )
50 : {
51 0 : U8_TRACE_BEGIN();
52 0 : assert ( NULL != target_folder );
53 0 : assert ( NULL != document_file_path );
54 0 : assert ( NULL != io_export_stat );
55 0 : u8_error_t export_err = U8_ERROR_NONE;
56 :
57 : /* transform file path to name */
58 : char temp_filename_buf[48];
59 0 : utf8stringbuf_t temp_filename = UTF8STRINGBUF(temp_filename_buf);
60 0 : u8_error_t err = io_exporter_private_get_filename( this_, document_file_path, temp_filename );
61 0 : const char *const document_file_name = (err==0) ? utf8stringbuf_get_string( &temp_filename ) : "document";
62 :
63 0 : if ( NULL != target_folder )
64 : {
65 0 : if ( ( export_type & IO_FILE_FORMAT_SVG ) != 0 )
66 : {
67 0 : export_err |= io_exporter_private_export_image_files( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, IO_FILE_FORMAT_SVG, target_folder, io_export_stat );
68 : }
69 :
70 0 : if ( ( export_type & ( IO_FILE_FORMAT_PDF | IO_FILE_FORMAT_DOCBOOK ) ) != 0 )
71 : {
72 0 : export_err |= io_exporter_private_export_image_files( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, IO_FILE_FORMAT_PDF, target_folder, io_export_stat );
73 : }
74 :
75 0 : if ( ( export_type & IO_FILE_FORMAT_PS ) != 0 )
76 : {
77 0 : export_err |= io_exporter_private_export_image_files( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, IO_FILE_FORMAT_PS, target_folder, io_export_stat );
78 : }
79 :
80 0 : if ( ( export_type & ( IO_FILE_FORMAT_PNG | IO_FILE_FORMAT_DOCBOOK | IO_FILE_FORMAT_HTML ) ) != 0 )
81 : {
82 0 : export_err |= io_exporter_private_export_image_files( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, IO_FILE_FORMAT_PNG, target_folder, io_export_stat );
83 : }
84 :
85 0 : if ( ( export_type & IO_FILE_FORMAT_TXT ) != 0 )
86 : {
87 0 : export_err |= io_exporter_private_export_image_files( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, IO_FILE_FORMAT_TXT, target_folder, io_export_stat );
88 : }
89 :
90 0 : if ( ( export_type & IO_FILE_FORMAT_DOCBOOK ) != 0 )
91 : {
92 0 : export_err |= io_exporter_private_export_document_file( this_, IO_FILE_FORMAT_DOCBOOK, target_folder, document_file_name, io_export_stat );
93 : }
94 :
95 0 : if ( ( export_type & IO_FILE_FORMAT_HTML ) != 0 )
96 : {
97 0 : export_err |= io_exporter_private_export_document_file( this_,
98 : IO_FILE_FORMAT_HTML,
99 : target_folder,
100 : document_file_name,
101 : io_export_stat
102 : );
103 0 : export_err |= io_exporter_private_export_document_file( this_,
104 : IO_FILE_FORMAT_CSS,
105 : target_folder,
106 : document_file_name,
107 : io_export_stat
108 : );
109 : }
110 :
111 0 : if ( ( export_type & IO_FILE_FORMAT_JSON ) != 0 )
112 : {
113 0 : export_err |= io_exporter_private_export_document_file( this_,
114 : IO_FILE_FORMAT_JSON,
115 : target_folder,
116 : document_file_name,
117 : io_export_stat
118 : );
119 0 : export_err |= io_exporter_private_export_document_file( this_,
120 : IO_FILE_FORMAT_SCHEMA,
121 : target_folder,
122 : document_file_name,
123 : io_export_stat
124 : );
125 : }
126 :
127 0 : if ( ( export_type & IO_FILE_FORMAT_XMI2 ) != 0 )
128 : {
129 0 : export_err |= io_exporter_private_export_document_file( this_, IO_FILE_FORMAT_XMI2, target_folder, document_file_name, io_export_stat );
130 : }
131 : }
132 : else /* target_folder == NULL */
133 : {
134 0 : U8_LOG_WARNING("selected target folder was NULL.");
135 0 : export_err = -1;
136 : }
137 :
138 0 : U8_TRACE_END_ERR(export_err);
139 0 : return export_err;
140 : }
141 :
142 0 : u8_error_t io_exporter_private_get_filename( io_exporter_t *this_,
143 : const char* path,
144 : utf8stringbuf_t out_base_filename )
145 : {
146 0 : U8_TRACE_BEGIN();
147 0 : assert ( NULL != path );
148 0 : u8_error_t err = U8_ERROR_NONE;
149 :
150 0 : utf8stringview_t path_view = UTF8STRINGVIEW_STR( path );
151 :
152 : utf8stringview_t before_winpath_sep;
153 : utf8stringview_t after_winpath_sep;
154 0 : const utf8error_t err_w = utf8stringview_split_at_last_str( &path_view, "\\", &before_winpath_sep, &after_winpath_sep );
155 0 : if ( err_w != UTF8ERROR_SUCCESS )
156 : {
157 0 : after_winpath_sep = path_view;
158 : }
159 : utf8stringview_t before_unixpath_sep;
160 : utf8stringview_t after_unixpath_sep;
161 0 : const utf8error_t err_u = utf8stringview_split_at_last_str( &after_winpath_sep, "/", &before_unixpath_sep, &after_unixpath_sep );
162 0 : if ( err_u != UTF8ERROR_SUCCESS )
163 : {
164 0 : after_unixpath_sep = after_winpath_sep;
165 : }
166 : utf8stringview_t before_dot;
167 : utf8stringview_t after_dot;
168 0 : const utf8error_t err_d = utf8stringview_split_at_last_str( &after_unixpath_sep, ".", &before_dot, &after_dot );
169 0 : if ( ( err_d != UTF8ERROR_SUCCESS )
170 0 : || ( utf8stringview_get_length( &before_dot ) == 0 )
171 0 : || ( utf8stringview_get_length( &after_dot ) == 0 ) )
172 : {
173 : /* either no dot found or the filename begins with dot or the filename ends on dot */
174 0 : before_dot = after_unixpath_sep;
175 : }
176 :
177 0 : err = utf8stringbuf_copy_view( &out_base_filename, &before_dot );
178 0 : if ( utf8stringbuf_get_length( &out_base_filename ) == 0 )
179 : {
180 0 : err = U8_ERROR_INPUT_EMPTY;
181 : }
182 :
183 0 : U8_TRACE_END_ERR(err);
184 0 : return err;
185 : }
186 :
187 0 : u8_error_t io_exporter_private_export_image_files( io_exporter_t *this_,
188 : data_id_t diagram_id,
189 : uint32_t max_recursion,
190 : io_file_format_t export_type,
191 : const char *target_folder,
192 : data_stat_t *io_export_stat )
193 : {
194 0 : U8_TRACE_BEGIN();
195 0 : assert ( NULL != target_folder );
196 0 : assert ( NULL != io_export_stat );
197 0 : U8_TRACE_INFO_STR("target_folder:", target_folder );
198 0 : const data_row_t diagram_row_id = data_id_get_row_id( &diagram_id );
199 0 : u8_error_t result = U8_ERROR_NONE;
200 :
201 : /* draw current diagram */
202 0 : if ( DATA_ROW_VOID != diagram_row_id )
203 : {
204 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
205 :
206 : /* determine filename */
207 0 : utf8stringbuf_copy_str( &((*this_).temp_filename), target_folder );
208 0 : utf8stringbuf_append_str( &((*this_).temp_filename), "/" );
209 0 : result |= io_exporter_private_get_filename_for_diagram( this_, diagram_id, utf8stringbuf_get_end( &((*this_).temp_filename) ) );
210 :
211 0 : if ( IO_FILE_FORMAT_SVG == export_type )
212 : {
213 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".svg" );
214 : }
215 0 : else if ( IO_FILE_FORMAT_PNG == export_type )
216 : {
217 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".png" );
218 : }
219 0 : else if ( IO_FILE_FORMAT_PDF == export_type )
220 : {
221 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".pdf" );
222 : }
223 0 : else if ( IO_FILE_FORMAT_PS == export_type )
224 : {
225 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".ps" );
226 : }
227 : else /* IO_FILE_FORMAT_TXT */
228 : {
229 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".txt" );
230 : }
231 0 : U8_LOG_EVENT_STR( "exporting diagram to file:", utf8stringbuf_get_string( &((*this_).temp_filename) ) );
232 :
233 0 : result |= io_exporter_export_image_file( this_,
234 : diagram_id,
235 : export_type,
236 0 : utf8stringbuf_get_string( &((*this_).temp_filename) ),
237 : io_export_stat
238 : );
239 : }
240 :
241 : /* recursion to children */
242 0 : if (( result == 0 )&&( max_recursion > 0 ))
243 : {
244 : u8_error_t db_err;
245 : data_small_set_t the_set;
246 0 : data_small_set_init( &the_set );
247 0 : db_err = data_database_reader_get_diagram_ids_by_parent_id ( (*this_).db_reader, diagram_row_id, &the_set );
248 0 : if ( db_err != U8_ERROR_NONE )
249 : {
250 0 : U8_LOG_ERROR("error reading database.");
251 0 : result = -1;
252 : }
253 : else
254 : {
255 0 : for ( uint32_t pos = 0; pos < data_small_set_get_count( &the_set ); pos ++ )
256 : {
257 : data_id_t probe_id;
258 0 : probe_id = data_small_set_get_id( &the_set, pos );
259 :
260 0 : result |= io_exporter_private_export_image_files( this_, probe_id, max_recursion-1, export_type, target_folder, io_export_stat );
261 :
262 0 : data_id_destroy( &probe_id );
263 : }
264 : }
265 0 : data_small_set_destroy( &the_set );
266 : }
267 :
268 0 : U8_TRACE_END_ERR( result );
269 0 : return result;
270 : }
271 :
272 0 : u8_error_t io_exporter_export_image_file( io_exporter_t *this_,
273 : data_id_t diagram_id,
274 : io_file_format_t export_type,
275 : const char *file_path,
276 : data_stat_t *io_export_stat )
277 : {
278 0 : U8_TRACE_BEGIN();
279 0 : assert ( data_id_is_valid( &diagram_id ) );
280 0 : assert ( NULL != file_path );
281 0 : assert ( NULL != io_export_stat );
282 0 : U8_TRACE_INFO_STR("file_path:", file_path );
283 0 : u8_error_t result = U8_ERROR_NONE;
284 :
285 : /* create surface */
286 0 : if (( IO_FILE_FORMAT_SVG == export_type )
287 0 : || ( IO_FILE_FORMAT_PDF == export_type )
288 0 : || ( IO_FILE_FORMAT_PS == export_type )
289 0 : || ( IO_FILE_FORMAT_PNG == export_type ) )
290 : {
291 0 : image_format_writer_init( &((*this_).temp_image_format_exporter ),
292 : (*this_).db_reader,
293 : &((*this_).temp_input_data),
294 : &((*this_).temp_profile)
295 : );
296 0 : result |= image_format_writer_render_diagram_to_file( &((*this_).temp_image_format_exporter ),
297 : diagram_id,
298 : export_type,
299 : file_path,
300 : io_export_stat
301 : );
302 0 : image_format_writer_destroy( &((*this_).temp_image_format_exporter ) );
303 : }
304 : else /* IO_FILE_FORMAT_TXT */
305 : {
306 : universal_file_output_stream_t text_output;
307 0 : universal_file_output_stream_init( &text_output );
308 0 : universal_output_stream_t *output = universal_file_output_stream_get_output_stream( &text_output );
309 :
310 : /* open file */
311 0 : result |= universal_file_output_stream_open( &text_output, file_path );
312 0 : if ( result == 0 )
313 : {
314 0 : u8_error_t write_err = U8_ERROR_NONE;
315 :
316 : /* temporarily use the temp_model_traversal */
317 : /* write file */
318 0 : document_element_writer_init( &((*this_).temp_format_writer ),
319 : (*this_).db_reader,
320 : IO_FILE_FORMAT_TXT,
321 : io_export_stat,
322 : output
323 : );
324 0 : io_export_diagram_traversal_init( &((*this_).temp_diagram_traversal),
325 : (*this_).db_reader,
326 : &((*this_).temp_input_data),
327 : io_export_stat,
328 : document_element_writer_get_element_writer( &((*this_).temp_format_writer) )
329 : );
330 0 : write_err |= document_element_writer_write_header( &((*this_).temp_format_writer), "DUMMY_TITLE" );
331 0 : write_err |= io_export_diagram_traversal_begin_and_walk_diagram ( &((*this_).temp_diagram_traversal), diagram_id, "NO_IMAGE_FILE" );
332 0 : write_err |= io_export_diagram_traversal_end_diagram ( &((*this_).temp_diagram_traversal), diagram_id );
333 0 : write_err |= document_element_writer_write_footer( &((*this_).temp_format_writer) );
334 0 : io_export_diagram_traversal_destroy( &((*this_).temp_diagram_traversal) );
335 0 : document_element_writer_destroy( &((*this_).temp_format_writer ) );
336 :
337 0 : if ( 0 != write_err )
338 : {
339 0 : U8_LOG_ERROR("error writing txt.");
340 0 : result = -1;
341 : }
342 :
343 : /* close file */
344 0 : result |= universal_file_output_stream_close( &text_output );
345 : }
346 :
347 0 : result |= universal_file_output_stream_destroy( &text_output );
348 :
349 0 : data_stat_inc_count ( io_export_stat, DATA_STAT_TABLE_DIAGRAM, DATA_STAT_SERIES_EXPORTED );
350 : }
351 :
352 0 : U8_TRACE_END_ERR( result );
353 0 : return result;
354 : }
355 :
356 0 : u8_error_t io_exporter_private_export_document_file( io_exporter_t *this_,
357 : io_file_format_t export_type,
358 : const char *target_folder,
359 : const char *document_file_name,
360 : data_stat_t *io_export_stat )
361 : {
362 0 : U8_TRACE_BEGIN();
363 0 : assert ( NULL != target_folder );
364 0 : assert ( NULL != document_file_name );
365 0 : assert ( NULL != io_export_stat );
366 0 : U8_TRACE_INFO_STR("target_folder:", target_folder );
367 0 : U8_TRACE_INFO_STR("document_file_name:", document_file_name );
368 0 : u8_error_t export_err = U8_ERROR_NONE;
369 :
370 : /* open file */
371 0 : utf8stringbuf_copy_str( &((*this_).temp_filename), target_folder );
372 0 : utf8stringbuf_append_str( &((*this_).temp_filename), "/" );
373 0 : utf8stringbuf_append_str( &((*this_).temp_filename), document_file_name );
374 0 : switch ( export_type )
375 : {
376 0 : case IO_FILE_FORMAT_DOCBOOK:
377 : {
378 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".xml" );
379 : }
380 0 : break;
381 :
382 0 : case IO_FILE_FORMAT_HTML:
383 : {
384 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".html" );
385 : }
386 0 : break;
387 :
388 0 : case IO_FILE_FORMAT_CSS:
389 : {
390 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".css" );
391 : }
392 0 : break;
393 :
394 0 : case IO_FILE_FORMAT_JSON:
395 : {
396 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".json" );
397 : }
398 0 : break;
399 :
400 0 : case IO_FILE_FORMAT_SCHEMA:
401 : {
402 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".schema" );
403 : }
404 0 : break;
405 :
406 0 : case IO_FILE_FORMAT_XMI2:
407 : {
408 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".xmi" );
409 : }
410 0 : break;
411 :
412 0 : default:
413 : {
414 0 : utf8stringbuf_append_str( &((*this_).temp_filename), ".unknown_format" );
415 0 : U8_LOG_ERROR("error: unknown_format.");
416 : }
417 0 : break;
418 : }
419 0 : U8_LOG_EVENT_STR( "exporting diagrams to document file:", utf8stringbuf_get_string( &((*this_).temp_filename) ) );
420 :
421 0 : export_err |= io_exporter_export_document_file( this_,
422 : export_type,
423 : document_file_name,
424 0 : utf8stringbuf_get_string( &((*this_).temp_filename) ),
425 : io_export_stat
426 : );
427 :
428 0 : U8_TRACE_END_ERR( export_err );
429 0 : return export_err;
430 : }
431 :
432 2 : u8_error_t io_exporter_export_document_file( io_exporter_t *this_,
433 : io_file_format_t export_type,
434 : const char *document_title,
435 : const char *file_path,
436 : data_stat_t *io_export_stat )
437 : {
438 2 : U8_TRACE_BEGIN();
439 2 : assert ( NULL != document_title );
440 2 : assert ( NULL != file_path );
441 2 : assert ( NULL != io_export_stat );
442 2 : U8_TRACE_INFO_STR("file_path:", file_path );
443 2 : u8_error_t export_err = U8_ERROR_NONE;
444 : universal_file_output_stream_t file_output;
445 2 : universal_file_output_stream_init( &file_output );
446 2 : universal_output_stream_t *output = universal_file_output_stream_get_output_stream( &file_output );
447 :
448 2 : export_err |= universal_file_output_stream_open( &file_output, file_path );
449 2 : if ( export_err == 0 )
450 : {
451 : /* write file */
452 2 : if ( IO_FILE_FORMAT_CSS == export_type )
453 : {
454 : document_css_writer_t css_writer;
455 0 : document_css_writer_init( &css_writer, output );
456 0 : export_err |= document_css_writer_write_stylesheet( &css_writer );
457 0 : document_css_writer_destroy( &css_writer );
458 : }
459 2 : else if ( IO_FILE_FORMAT_SCHEMA == export_type )
460 : {
461 : json_schema_writer_t schema_writer;
462 0 : json_schema_writer_init( &schema_writer, output );
463 0 : export_err |= json_schema_writer_write_schema( &schema_writer );
464 0 : json_schema_writer_destroy( &schema_writer );
465 : }
466 2 : else if ( IO_FILE_FORMAT_XMI2 == export_type )
467 : {
468 0 : xmi_element_writer_init( &((*this_).temp_xmi_writer ), io_export_stat, output );
469 : /* init the model_traversal */
470 0 : io_export_model_traversal_init( &((*this_).temp_model_traversal),
471 : (*this_).db_reader,
472 : &((*this_).temp_input_data),
473 : io_export_stat,
474 : xmi_element_writer_get_element_writer( &((*this_).temp_xmi_writer) )
475 : );
476 : /* write the document */
477 0 : export_err |= xmi_element_writer_write_header( &((*this_).temp_xmi_writer), document_title );
478 0 : export_err |= xmi_element_writer_start_main( &((*this_).temp_xmi_writer), document_title );
479 0 : xmi_element_writer_set_mode( &((*this_).temp_xmi_writer ), XMI_WRITER_PASS_BASE );
480 0 : export_err |= io_export_model_traversal_walk_model_nodes( &((*this_).temp_model_traversal) );
481 0 : export_err |= xmi_element_writer_end_main( &((*this_).temp_xmi_writer) );
482 0 : xmi_element_writer_set_mode( &((*this_).temp_xmi_writer ), XMI_WRITER_PASS_PROFILE );
483 0 : export_err |= io_export_model_traversal_walk_model_nodes( &((*this_).temp_model_traversal) );
484 0 : export_err |= xmi_element_writer_write_footer( &((*this_).temp_xmi_writer) );
485 :
486 0 : io_export_model_traversal_destroy( &((*this_).temp_model_traversal) );
487 0 : xmi_element_writer_destroy( &((*this_).temp_xmi_writer ) );
488 : }
489 2 : else if ( IO_FILE_FORMAT_JSON == export_type )
490 : {
491 2 : json_element_writer_init( &((*this_).temp_json_writer ), io_export_stat, output );
492 2 : export_err |= json_element_writer_write_header( &((*this_).temp_json_writer), document_title );
493 :
494 : /* init the diagram_traversal */
495 : {
496 2 : io_export_diagram_traversal_init( &((*this_).temp_diagram_traversal),
497 : (*this_).db_reader,
498 : &((*this_).temp_input_data),
499 : io_export_stat,
500 : json_element_writer_get_element_writer( &((*this_).temp_json_writer) )
501 : );
502 : /* write the document */
503 2 : json_element_writer_set_mode( &((*this_).temp_json_writer ), JSON_WRITER_PASS_VIEWS );
504 2 : export_err |= json_element_writer_start_main( &((*this_).temp_json_writer), document_title );
505 2 : export_err |= io_exporter_private_export_document_part( this_, DATA_ID_VOID, IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH, io_export_stat );
506 2 : export_err |= json_element_writer_end_main( &((*this_).temp_json_writer) );
507 :
508 2 : io_export_diagram_traversal_destroy( &((*this_).temp_diagram_traversal) );
509 : }
510 :
511 : /* init the model_traversal */
512 : {
513 2 : io_export_flat_traversal_init( &((*this_).temp_flat_traversal),
514 : (*this_).db_reader,
515 : io_export_stat,
516 : json_element_writer_get_element_writer( &((*this_).temp_json_writer) )
517 : );
518 : /* write the document */
519 2 : json_element_writer_set_mode( &((*this_).temp_json_writer ), JSON_WRITER_PASS_NODES );
520 2 : export_err |= json_element_writer_start_main( &((*this_).temp_json_writer), document_title );
521 2 : export_err |= io_export_flat_traversal_iterate_classifiers( &((*this_).temp_flat_traversal), false );
522 2 : export_err |= json_element_writer_end_main( &((*this_).temp_json_writer) );
523 :
524 2 : json_element_writer_set_mode( &((*this_).temp_json_writer ), JSON_WRITER_PASS_EDGES );
525 2 : export_err |= json_element_writer_start_main( &((*this_).temp_json_writer), document_title );
526 2 : export_err |= io_export_flat_traversal_iterate_classifiers( &((*this_).temp_flat_traversal), false );
527 2 : export_err |= json_element_writer_end_main( &((*this_).temp_json_writer) );
528 :
529 2 : io_export_flat_traversal_destroy( &((*this_).temp_flat_traversal) );
530 : }
531 :
532 2 : export_err |= json_element_writer_write_footer( &((*this_).temp_json_writer) );
533 2 : json_element_writer_destroy( &((*this_).temp_json_writer ) );
534 : }
535 : else
536 : {
537 0 : document_element_writer_init( &((*this_).temp_format_writer ),
538 : (*this_).db_reader,
539 : export_type,
540 : io_export_stat,
541 : output
542 : );
543 : /* init the diagram_traversal */
544 0 : io_export_diagram_traversal_init( &((*this_).temp_diagram_traversal),
545 : (*this_).db_reader,
546 : &((*this_).temp_input_data),
547 : io_export_stat,
548 : document_element_writer_get_element_writer( &((*this_).temp_format_writer) )
549 : );
550 : /* write the document */
551 0 : export_err |= document_element_writer_write_header( &((*this_).temp_format_writer), document_title );
552 0 : export_err |= document_element_writer_start_toc( &((*this_).temp_format_writer) );
553 0 : export_err |= io_exporter_private_export_table_of_contents( this_,
554 0 : DATA_ID_VOID,
555 : IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH,
556 : &((*this_).temp_format_writer)
557 : );
558 0 : export_err |= document_element_writer_end_toc( &((*this_).temp_format_writer) );
559 0 : export_err |= document_element_writer_start_main( &((*this_).temp_format_writer), document_title );
560 0 : export_err |= io_exporter_private_export_document_part( this_, DATA_ID_VOID,
561 : IO_EXPORTER_MAX_DIAGRAM_TREE_DEPTH,
562 : io_export_stat
563 : );
564 0 : export_err |= document_element_writer_end_main( &((*this_).temp_format_writer) );
565 0 : export_err |= document_element_writer_write_footer( &((*this_).temp_format_writer) );
566 :
567 0 : io_export_diagram_traversal_destroy( &((*this_).temp_diagram_traversal) );
568 0 : document_element_writer_destroy( &((*this_).temp_format_writer ) );
569 : }
570 :
571 : /* close file */
572 2 : export_err |= universal_file_output_stream_close( &file_output );
573 : }
574 :
575 2 : export_err |= universal_file_output_stream_destroy( &file_output );
576 :
577 2 : U8_TRACE_END_ERR( export_err );
578 2 : return export_err;
579 : }
580 :
581 2 : u8_error_t io_exporter_private_export_document_part( io_exporter_t *this_,
582 : data_id_t diagram_id,
583 : uint32_t max_recursion,
584 : data_stat_t *io_export_stat )
585 : {
586 2 : U8_TRACE_BEGIN();
587 2 : assert ( NULL != io_export_stat );
588 2 : const data_row_t diagram_row_id = data_id_get_row_id( &diagram_id );
589 2 : u8_error_t export_err = U8_ERROR_NONE;
590 :
591 : /* write part for current diagram */
592 2 : if ( DATA_ROW_VOID != diagram_row_id )
593 : {
594 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
595 :
596 : /* determine filename */
597 0 : export_err |= io_exporter_private_get_filename_for_diagram( this_, diagram_id, (*this_).temp_filename );
598 :
599 :
600 : /* write doc part */
601 0 : export_err |= io_export_diagram_traversal_begin_and_walk_diagram( &((*this_).temp_diagram_traversal),
602 : diagram_id,
603 0 : utf8stringbuf_get_string( &((*this_).temp_filename) )
604 : );
605 : }
606 :
607 : /* recursion to children */
608 2 : if (( export_err == 0 )&&( max_recursion > 0 ))
609 : {
610 : u8_error_t db_err;
611 : data_small_set_t the_set;
612 2 : data_small_set_init( &the_set );
613 2 : db_err = data_database_reader_get_diagram_ids_by_parent_id ( (*this_).db_reader, diagram_row_id, &the_set );
614 2 : if ( db_err != U8_ERROR_NONE )
615 : {
616 0 : U8_LOG_ERROR("error reading database.");
617 0 : export_err |= -1;
618 : }
619 : else
620 : {
621 2 : const uint32_t child_count = data_small_set_get_count( &the_set );
622 2 : for ( uint32_t pos = 0; pos < child_count; pos ++ )
623 : {
624 0 : data_id_t probe_id = data_small_set_get_id( &the_set, pos );
625 :
626 0 : export_err |= io_exporter_private_export_document_part( this_, probe_id, max_recursion-1, io_export_stat );
627 :
628 0 : data_id_destroy( &probe_id );
629 : }
630 : }
631 2 : data_small_set_destroy( &the_set );
632 : }
633 :
634 : /* end diagram section */
635 2 : if ( DATA_ROW_VOID != diagram_row_id )
636 : {
637 : /* write doc part */
638 0 : export_err |= io_export_diagram_traversal_end_diagram( &((*this_).temp_diagram_traversal), diagram_id );
639 : }
640 :
641 2 : U8_TRACE_END_ERR( export_err );
642 2 : return export_err;
643 : }
644 :
645 0 : u8_error_t io_exporter_private_export_table_of_contents( io_exporter_t *this_,
646 : data_id_t diagram_id,
647 : uint32_t max_recursion,
648 : document_element_writer_t *format_writer )
649 : {
650 0 : U8_TRACE_BEGIN();
651 0 : assert ( NULL != format_writer );
652 0 : const data_row_t diagram_row_id = data_id_get_row_id( &diagram_id );
653 0 : u8_error_t export_err = U8_ERROR_NONE;
654 :
655 : /* write entry for current diagram */
656 0 : if ( DATA_ROW_VOID != diagram_row_id )
657 : {
658 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
659 :
660 0 : export_err |= document_element_writer_start_toc_entry( format_writer );
661 :
662 : /* load data to be drawn */
663 : u8_error_t db_err;
664 0 : db_err = data_database_reader_get_diagram_by_id ( (*this_).db_reader, diagram_row_id, &((*this_).temp_diagram) );
665 0 : if ( db_err != U8_ERROR_NONE )
666 : {
667 0 : U8_LOG_ERROR("error reading database.");
668 0 : export_err |= -1;
669 : }
670 : else
671 : {
672 0 : export_err |= document_element_writer_write_toc_entry ( format_writer, &((*this_).temp_diagram) );
673 0 : data_diagram_destroy( &((*this_).temp_diagram) );
674 : }
675 : }
676 :
677 : /* recursion to children */
678 0 : if (( export_err == 0 )&&( max_recursion > 0 ))
679 : {
680 : u8_error_t db_err;
681 : data_small_set_t the_set;
682 0 : data_small_set_init( &the_set );
683 0 : db_err = data_database_reader_get_diagram_ids_by_parent_id ( (*this_).db_reader, diagram_row_id, &the_set );
684 0 : if ( db_err != U8_ERROR_NONE )
685 : {
686 0 : U8_LOG_ERROR("error reading database.");
687 0 : export_err |= -1;
688 : }
689 : else
690 : {
691 0 : const uint32_t child_count = data_small_set_get_count( &the_set );
692 0 : if ( child_count != 0 )
693 : {
694 0 : export_err |= document_element_writer_start_toc_sublist( format_writer );
695 0 : for ( uint32_t pos = 0; pos < child_count; pos ++ )
696 : {
697 0 : data_id_t probe_id = data_small_set_get_id( &the_set, pos );
698 :
699 0 : export_err |= io_exporter_private_export_table_of_contents( this_, probe_id, max_recursion-1, format_writer );
700 :
701 0 : data_id_destroy( &probe_id );
702 : }
703 0 : export_err |= document_element_writer_end_toc_sublist ( format_writer );
704 : }
705 : }
706 0 : data_small_set_destroy( &the_set );
707 : }
708 :
709 : /* end toc entry */
710 0 : if ( DATA_ROW_VOID != diagram_row_id )
711 : {
712 0 : export_err |= document_element_writer_end_toc_entry( format_writer );
713 : }
714 :
715 0 : U8_TRACE_END_ERR( export_err );
716 0 : return export_err;
717 : }
718 :
719 0 : u8_error_t io_exporter_private_get_filename_for_diagram( io_exporter_t *this_,
720 : data_id_t diagram_id,
721 : utf8stringbuf_t filename )
722 : {
723 0 : U8_TRACE_BEGIN();
724 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
725 0 : u8_error_t result = U8_ERROR_NONE;
726 0 : utf8stringbuf_clear( &filename );
727 :
728 : u8_error_t db_err;
729 0 : db_err = data_database_reader_get_diagram_by_id ( (*this_).db_reader, data_id_get_row_id( &diagram_id ), &((*this_).temp_diagram) );
730 0 : if ( db_err != U8_ERROR_NONE )
731 : {
732 0 : U8_LOG_ERROR("error reading database.");
733 0 : result |= -1;
734 : }
735 : else
736 : {
737 : const char *diag_name;
738 0 : diag_name = data_diagram_get_name_const( &((*this_).temp_diagram) );
739 :
740 : /* determine filename */
741 0 : data_id_to_utf8stringbuf( &diagram_id, filename );
742 0 : utf8stringbuf_append_str( &filename, "_" );
743 0 : io_exporter_private_append_valid_chars_to_filename( this_, diag_name, filename );
744 0 : data_diagram_destroy( &((*this_).temp_diagram) );
745 : }
746 :
747 0 : U8_TRACE_END_ERR( result );
748 0 : return result;
749 : }
750 :
751 0 : void io_exporter_private_append_valid_chars_to_filename( io_exporter_t *this_,
752 : const char* name,
753 : utf8stringbuf_t filename )
754 : {
755 0 : U8_TRACE_BEGIN();
756 0 : assert( NULL != name );
757 0 : U8_TRACE_INFO_STR( "name:", name );
758 :
759 0 : bool finished = false;
760 : static const int MAX_APPEND_CHARS = 64;
761 0 : for ( int pos = 0; ( pos < MAX_APPEND_CHARS ) && ( ! finished ); pos ++ )
762 : {
763 0 : char probe = name[pos];
764 0 : if ( probe == '\0' )
765 : {
766 0 : finished = true;
767 : }
768 0 : else if (( 'A' <= probe ) && ( probe <= 'Z' ))
769 : {
770 0 : utf8stringbuf_append_char( &filename, probe );
771 : }
772 0 : else if (( 'a' <= probe ) && ( probe <= 'z' ))
773 : {
774 0 : utf8stringbuf_append_char( &filename, probe );
775 : }
776 0 : else if (( '0' <= probe ) && ( probe <= '9' ))
777 : {
778 0 : utf8stringbuf_append_char( &filename, probe );
779 : }
780 0 : else if ( '-' == probe )
781 : {
782 0 : utf8stringbuf_append_char( &filename, probe );
783 : }
784 0 : else if ( '_' == probe )
785 : {
786 0 : utf8stringbuf_append_char( &filename, probe );
787 : }
788 0 : else if ( ' ' == probe )
789 : {
790 0 : utf8stringbuf_append_char( &filename, '_' );
791 : }
792 : }
793 :
794 0 : U8_TRACE_END();
795 0 : }
796 :
797 :
798 : /*
799 : Copyright 2016-2025 Andreas Warnke
800 :
801 : Licensed under the Apache License, Version 2.0 (the "License");
802 : you may not use this file except in compliance with the License.
803 : You may obtain a copy of the License at
804 :
805 : http://www.apache.org/licenses/LICENSE-2.0
806 :
807 : Unless required by applicable law or agreed to in writing, software
808 : distributed under the License is distributed on an "AS IS" BASIS,
809 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
810 : See the License for the specific language governing permissions and
811 : limitations under the License.
812 : */
|