LCOV - code coverage report
Current view: top level - io/source - io_exporter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 68 347 19.6 %
Date: 2025-09-25 21:07:53 Functions: 4 12 33.3 %

          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             : */

Generated by: LCOV version 1.16