LCOV - code coverage report
Current view: top level - ctrl/source - ctrl_consistency_checker.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 329 361 91.1 %
Date: 2024-12-21 18:34:41 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* File: ctrl_consistency_checker.c; Copyright and License: see below */
       2             : 
       3             : #include "ctrl_consistency_checker.h"
       4             : #include "storage/data_database_consistency_checker.h"
       5             : #include "entity/data_id.h"
       6             : #include "u8/u8_trace.h"
       7             : #include "u8/u8_log.h"
       8             : #include <assert.h>
       9             : 
      10          84 : void ctrl_consistency_checker_init ( ctrl_consistency_checker_t *this_,
      11             :                                      data_database_t *database,
      12             :                                      data_database_reader_t *db_reader,
      13             :                                      data_database_writer_t *db_writer )
      14             : {
      15          84 :     U8_TRACE_BEGIN();
      16          84 :     assert( NULL != database );
      17          84 :     assert( NULL != db_reader );
      18          84 :     assert( NULL != db_writer );
      19             : 
      20          84 :     (*this_).database = database;
      21          84 :     (*this_).db_reader = db_reader;
      22          84 :     (*this_).db_writer = db_writer;
      23             : 
      24          84 :     data_database_consistency_checker_init( &((*this_).db_checker), database );
      25             : 
      26          84 :     U8_TRACE_END();
      27          84 : }
      28             : 
      29          84 : void ctrl_consistency_checker_destroy ( ctrl_consistency_checker_t *this_ )
      30             : {
      31          84 :     U8_TRACE_BEGIN();
      32             : 
      33          84 :     data_database_consistency_checker_destroy( &((*this_).db_checker) );
      34             : 
      35          84 :     (*this_).database = NULL;
      36          84 :     (*this_).db_reader = NULL;
      37          84 :     (*this_).db_writer = NULL;
      38             : 
      39          84 :     U8_TRACE_END();
      40          84 : }
      41             : 
      42          30 : u8_error_t ctrl_consistency_checker_repair_database ( ctrl_consistency_checker_t *this_,
      43             :                                                       bool modify_db,
      44             :                                                       uint32_t *out_err,
      45             :                                                       uint32_t *out_fix,
      46             :                                                       utf8stream_writer_t *out_english_report )
      47             : {
      48          30 :     U8_TRACE_BEGIN();
      49          30 :     assert ( NULL != out_english_report );
      50          30 :     u8_error_t err_result = U8_ERROR_NONE;
      51          30 :     uint32_t error_count = 0;
      52          30 :     uint32_t fix_count = 0;
      53             : 
      54             :     /* write report title */
      55          30 :     if ( modify_db )
      56             :     {
      57          10 :         utf8stream_writer_write_str( out_english_report, "TITLE: Repair database\n" );
      58             :     }
      59             :     else
      60             :     {
      61          20 :         utf8stream_writer_write_str( out_english_report, "TITLE: Check database\n" );
      62             :     }
      63             : 
      64             :     /* == find inconsistencies in drawings == */
      65             : 
      66             :     /* get all root diagrams */
      67          30 :     err_result |= ctrl_consistency_checker_private_ensure_single_root_diagram( this_, modify_db, &error_count, &fix_count, out_english_report );
      68             : 
      69             :     /* find invalid and circular diagram parent links */
      70          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_diagram_parents( this_, modify_db, &error_count, &fix_count, out_english_report );
      71             : 
      72             :     /* find nonreferencing diagramelements */
      73          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_diagramelements( this_, modify_db, &error_count, &fix_count, out_english_report );
      74             : 
      75             :     /* find illreferencing diagramelements */
      76          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_diagele_features( this_, modify_db, &error_count, &fix_count, out_english_report );
      77             : 
      78             :     /* find unreferenced, invisible classifiers */
      79          30 :     err_result |= ctrl_consistency_checker_private_ensure_referenced_classifiers( this_, modify_db, &error_count, &fix_count, out_english_report );
      80             : 
      81             :     /* == find inconsistencies in meta model == */
      82             : 
      83             :     /* find nonreferencing features */
      84          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_feature_parents( this_, modify_db, &error_count, &fix_count, out_english_report );
      85             : 
      86             :     /* find nonreferencing relationships */
      87          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_relationship_classifiers( this_, modify_db, &error_count, &fix_count, out_english_report );
      88             : 
      89             :     /* find illreferencing relationships */
      90          30 :     err_result |= ctrl_consistency_checker_private_ensure_valid_relationship_features( this_, modify_db, &error_count, &fix_count, out_english_report );
      91             : 
      92             :     /* prepare results and return */
      93          30 :     if ( NULL != out_err )
      94             :     {
      95          30 :         (*out_err) = error_count;
      96             :     }
      97          30 :     if ( NULL != out_fix )
      98             :     {
      99          30 :         (*out_fix) = fix_count;
     100             :     }
     101             : 
     102             :     /* write report summary */
     103          30 :     const char *db_filename = data_database_get_filename_ptr ( (*this_).database );
     104          30 :     utf8stream_writer_write_str( out_english_report, "SUMMARY: " );
     105          30 :     if ( db_filename != NULL )
     106             :     {
     107          30 :         utf8stream_writer_write_str( out_english_report, "\n    File: " );
     108          30 :         utf8stream_writer_write_str( out_english_report, db_filename );
     109             :     }
     110          30 :     utf8stream_writer_write_str( out_english_report, "\n    Errors found: " );
     111          30 :     utf8stream_writer_write_int( out_english_report, error_count );
     112          30 :     utf8stream_writer_write_str( out_english_report, "\n    Errors fixed: " );
     113          30 :     utf8stream_writer_write_int( out_english_report, fix_count );
     114          30 :     utf8stream_writer_write_str( out_english_report, "\n" );
     115             : 
     116             :     /* if not all errors fixed, set result to U8_ERROR_DB_STRUCTURE */
     117          30 :     if ( error_count > fix_count )
     118             :     {
     119          10 :         err_result |= U8_ERROR_DB_STRUCTURE;
     120             :     }
     121             : 
     122          30 :     U8_TRACE_END_ERR( err_result );
     123          30 :     return err_result;
     124             : }
     125             : 
     126          30 : u8_error_t ctrl_consistency_checker_private_ensure_single_root_diagram ( ctrl_consistency_checker_t *this_,
     127             :                                                                          bool modify_db,
     128             :                                                                          uint32_t *io_err,
     129             :                                                                          uint32_t *io_fix,
     130             :                                                                          utf8stream_writer_t *out_english_report )
     131             : {
     132          30 :     U8_TRACE_BEGIN();
     133          30 :     assert ( NULL != io_err );
     134          30 :     assert ( NULL != io_fix );
     135          30 :     assert ( NULL != out_english_report );
     136          30 :     u8_error_t result = U8_ERROR_NONE;
     137             : 
     138             :     /* write report title */
     139          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure a single root diagram\n" );
     140             : 
     141             :     /* get all root diagrams */
     142             :     data_small_set_t all_roots;
     143          30 :     data_small_set_init( &all_roots );
     144             :     data_diagram_iterator_t diagram_iterator;
     145          30 :     result |= data_diagram_iterator_init_empty( &diagram_iterator );
     146             : 
     147          30 :     result |= data_database_reader_get_diagrams_by_parent_id( (*this_).db_reader,
     148             :                                                               DATA_ROW_VOID,
     149             :                                                               &diagram_iterator
     150             :                                                             );
     151             : 
     152          30 :     if ( U8_ERROR_NONE != result )
     153             :     {
     154           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     155             :     }
     156             : 
     157          62 :     while ( data_diagram_iterator_has_next( &diagram_iterator ) )
     158             :     {
     159          32 :         result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram) );
     160          32 :         result |= data_small_set_add_obj( &all_roots, data_diagram_get_data_id( &((*this_).temp_diagram) ) );
     161             : 
     162          32 :         utf8stream_writer_write_str( out_english_report, "    INFO: Root diagram: " );
     163          32 :         utf8stream_writer_write_int( out_english_report, data_diagram_get_row_id( &((*this_).temp_diagram) ) );
     164          32 :         utf8stream_writer_write_str( out_english_report, ": " );
     165          32 :         utf8stream_writer_write_str( out_english_report, data_diagram_get_name_const( &((*this_).temp_diagram) ) );
     166          32 :         utf8stream_writer_write_str( out_english_report, "\n" );
     167             :     }
     168          30 :     const uint_fast32_t root_diagram_count = data_small_set_get_count( &all_roots );
     169          30 :     utf8stream_writer_write_str( out_english_report, "    ROOT DIAGRAM COUNT: " );
     170          30 :     utf8stream_writer_write_int( out_english_report, root_diagram_count );
     171          30 :     utf8stream_writer_write_str( out_english_report, "\n" );
     172          30 :     result |= data_diagram_iterator_destroy( &diagram_iterator );
     173             : 
     174          30 :     if ( root_diagram_count == 0 )
     175             :     {
     176           0 :         (*io_err) ++;
     177           0 :         utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Create a diagram via the GUI.\n" );
     178             :     }
     179          30 :     else if ( root_diagram_count > 1 )
     180             :     {
     181           2 :         (*io_err) += (root_diagram_count-1) ;
     182           2 :         const data_id_t proposed_root_diagram = data_small_set_get_id( &all_roots, 0 );
     183           2 :         const data_row_t proposed_root_diagram_id = data_id_get_row_id( &proposed_root_diagram );
     184           2 :         if ( ! modify_db )
     185             :         {
     186           1 :             utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Attach additional root diagrams below the first: " );
     187           1 :             utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id );
     188           1 :             utf8stream_writer_write_str( out_english_report, "\n" );
     189             :         }
     190             :         else
     191             :         {
     192           2 :             for ( int list_pos = 1; list_pos < root_diagram_count; list_pos ++ )
     193             :             {
     194           1 :                 const data_id_t proposed_child_diagram = data_small_set_get_id( &all_roots, list_pos );
     195           1 :                 const data_row_t proposed_child_diagram_id = data_id_get_row_id( &proposed_child_diagram );
     196             :                 const u8_error_t data_err
     197           1 :                     = data_database_writer_update_diagram_parent_id( (*this_).db_writer,
     198             :                                                                      proposed_child_diagram_id,
     199             :                                                                      proposed_root_diagram_id,
     200             :                                                                      NULL
     201             :                                                                    );
     202           1 :                 if ( U8_ERROR_NONE == data_err )
     203             :                 {
     204           1 :                     utf8stream_writer_write_str( out_english_report, "    FIX: Diagram " );
     205           1 :                     utf8stream_writer_write_int( out_english_report, proposed_child_diagram_id );
     206           1 :                     utf8stream_writer_write_str( out_english_report, " attached to " );
     207           1 :                     utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id);
     208           1 :                     utf8stream_writer_write_str( out_english_report, "\n" );
     209           1 :                     (*io_fix) ++;
     210             :                 }
     211             :                 else
     212             :                 {
     213           0 :                     utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     214           0 :                     result |= data_err;
     215             :                 }
     216             :             }
     217             :         }
     218             :     }
     219          30 :     data_small_set_destroy( &all_roots );
     220             : 
     221          30 :     U8_TRACE_END_ERR( result );
     222          30 :     return result;
     223             : }
     224             : 
     225          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagram_parents ( ctrl_consistency_checker_t *this_,
     226             :                                                                            bool modify_db,
     227             :                                                                            uint32_t *io_err,
     228             :                                                                            uint32_t *io_fix,
     229             :                                                                            utf8stream_writer_t *out_english_report )
     230             : {
     231          30 :     U8_TRACE_BEGIN();
     232          30 :     assert ( NULL != io_err );
     233          30 :     assert ( NULL != out_english_report );
     234          30 :     u8_error_t err_result = U8_ERROR_NONE;
     235             :     u8_error_t data_err;
     236             : 
     237             :     /* write report title */
     238          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that no circular/invalid references of diagram parents exist\n" );
     239             : 
     240             :     data_small_set_t circ_ref;
     241          30 :     data_small_set_init( &circ_ref );
     242          30 :     data_err = data_database_consistency_checker_find_circular_diagram_parents ( &((*this_).db_checker), &circ_ref );
     243          30 :     if ( U8_ERROR_NONE == data_err )
     244             :     {
     245          30 :         uint32_t circ_ref_count = data_small_set_get_count( &circ_ref );
     246             : 
     247          30 :         utf8stream_writer_write_str( out_english_report, "    DIAGRAMS WITH CIRCLUAR OR INVALID PARENT REFERENCES: " );
     248          30 :         utf8stream_writer_write_int( out_english_report, circ_ref_count );
     249          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     250             : 
     251          30 :         if ( circ_ref_count != 0 )
     252             :         {
     253           4 :             (*io_err) += circ_ref_count;
     254             : 
     255             :             /* get the root diagram */
     256           4 :             data_row_t root_diag_id = DATA_ROW_VOID;
     257             :             {
     258             :                 data_diagram_iterator_t diagram_iterator;
     259           4 :                 err_result |= data_diagram_iterator_init_empty( &diagram_iterator );
     260           4 :                 err_result |= data_database_reader_get_diagrams_by_parent_id( (*this_).db_reader,
     261             :                                                                               DATA_ROW_VOID,
     262             :                                                                               &diagram_iterator
     263             :                                                                             );
     264           4 :                 if (( U8_ERROR_NONE == err_result )&& data_diagram_iterator_has_next( &diagram_iterator ) )
     265             :                 {
     266           4 :                     err_result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram) );
     267           4 :                     root_diag_id = data_diagram_get_row_id( &((*this_).temp_diagram) );
     268             :                 }
     269           4 :                 err_result |= data_diagram_iterator_destroy( &diagram_iterator );
     270             :             }
     271             : 
     272           4 :             if ( ! modify_db )
     273             :             {
     274           2 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Move " );
     275           2 :                 utf8stream_writer_write_int( out_english_report, circ_ref_count );
     276           2 :                 utf8stream_writer_write_str( out_english_report, " diagrams below root diagram " );
     277           2 :                 utf8stream_writer_write_int( out_english_report, root_diag_id );
     278           2 :                 utf8stream_writer_write_str( out_english_report, ".\n" );
     279             :             }
     280             :             else
     281             :             {
     282           6 :                 for ( int list_pos = 0; list_pos < circ_ref_count; list_pos ++ )
     283             :                 {
     284           4 :                     data_id_t diagram_id = data_small_set_get_id( &circ_ref, list_pos );
     285           4 :                     data_row_t diagram_row_id = data_id_get_row_id( &diagram_id );
     286             : 
     287           4 :                     data_err = data_database_writer_update_diagram_parent_id ( (*this_).db_writer,
     288             :                                                                                diagram_row_id,
     289             :                                                                                root_diag_id,
     290             :                                                                                NULL /*out_old_diagram*/
     291             :                                                                              );
     292           4 :                     if ( U8_ERROR_NONE == data_err )
     293             :                     {
     294           4 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Diagram " );
     295           4 :                         utf8stream_writer_write_int( out_english_report, diagram_row_id );
     296           4 :                         utf8stream_writer_write_str( out_english_report, " moved below root diagram " );
     297           4 :                         utf8stream_writer_write_int( out_english_report, root_diag_id );
     298           4 :                         utf8stream_writer_write_str( out_english_report, ".\n" );
     299           4 :                         (*io_fix) ++;
     300             :                     }
     301             :                     else
     302             :                     {
     303           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     304           0 :                         err_result |= data_err;
     305             :                     }
     306             :                 }
     307             :             }
     308             :         }
     309             :     }
     310             :     else
     311             :     {
     312           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     313           0 :         err_result |= data_err;
     314             :     }
     315          30 :     data_small_set_destroy( &circ_ref );
     316             : 
     317          30 :     U8_TRACE_END_ERR( err_result );
     318          30 :     return err_result;
     319             : }
     320             : 
     321          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagramelements ( ctrl_consistency_checker_t *this_,
     322             :                                                                            bool modify_db,
     323             :                                                                            uint32_t *io_err,
     324             :                                                                            uint32_t *io_fix,
     325             :                                                                            utf8stream_writer_t *out_english_report )
     326             : {
     327          30 :     U8_TRACE_BEGIN();
     328          30 :     assert ( NULL != io_err );
     329          30 :     assert ( NULL != io_fix );
     330          30 :     assert ( NULL != out_english_report );
     331          30 :     u8_error_t err_result = U8_ERROR_NONE;
     332             :     u8_error_t data_err;
     333             : 
     334             :     /* write report title */
     335          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference valid diagrams and classifiers\n" );
     336             : 
     337             :     data_small_set_t unref;
     338          30 :     data_small_set_init( &unref );
     339          30 :     data_err = data_database_consistency_checker_find_nonreferencing_diagramelements ( &((*this_).db_checker), &unref );
     340          30 :     if ( U8_ERROR_NONE == data_err )
     341             :     {
     342          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     343             : 
     344          30 :         utf8stream_writer_write_str( out_english_report, "    NONREFERENCING DIAGRAMELEMENTS COUNT: " );
     345          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     346          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     347             : 
     348          30 :         if ( unref_count != 0 )
     349             :         {
     350           2 :             (*io_err) += unref_count;
     351             : 
     352           2 :             if ( ! modify_db )
     353             :             {
     354           1 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Delete " );
     355           1 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     356           1 :                 utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
     357             :             }
     358             :             else
     359             :             {
     360           4 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     361             :                 {
     362           3 :                     data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
     363           3 :                     data_row_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
     364           3 :                     data_err = data_database_writer_delete_diagramelement ( (*this_).db_writer, diagramelement_row_id, NULL );
     365           3 :                     if ( U8_ERROR_NONE == data_err )
     366             :                     {
     367           3 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Diagramelement " );
     368           3 :                         utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
     369           3 :                         utf8stream_writer_write_str( out_english_report, " deleted.\n" );
     370           3 :                         (*io_fix) ++;
     371             :                     }
     372             :                     else
     373             :                     {
     374           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     375           0 :                         err_result |= data_err;
     376             :                     }
     377             :                 }
     378             :             }
     379             :         }
     380             :     }
     381             :     else
     382             :     {
     383           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     384           0 :         err_result |= data_err;
     385             :     }
     386             : 
     387          30 :     U8_TRACE_END_ERR( err_result );
     388          30 :     return err_result;
     389             : }
     390             : 
     391          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagele_features ( ctrl_consistency_checker_t *this_,
     392             :                                                                             bool modify_db,
     393             :                                                                             uint32_t *io_err,
     394             :                                                                             uint32_t *io_fix,
     395             :                                                                             utf8stream_writer_t *out_english_report )
     396             : {
     397          30 :     U8_TRACE_BEGIN();
     398          30 :     assert ( NULL != io_err );
     399          30 :     assert ( NULL != io_fix );
     400          30 :     assert ( NULL != out_english_report );
     401          30 :     u8_error_t err_result = U8_ERROR_NONE;
     402             :     u8_error_t data_err;
     403             : 
     404             :     /* write report title */
     405          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference NULL or valid features\n" );
     406             : 
     407             :     data_small_set_t unref;
     408          30 :     data_small_set_init( &unref );
     409          30 :     data_err = data_database_consistency_checker_find_invalid_focused_features ( &((*this_).db_checker), &unref );
     410          30 :     if ( U8_ERROR_NONE == data_err )
     411             :     {
     412          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     413             : 
     414          30 :         utf8stream_writer_write_str( out_english_report, "    ILLREFERENCING DIAGRAMELEMENTS COUNT: " );
     415          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     416          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     417             : 
     418          30 :         if ( unref_count != 0 )
     419             :         {
     420           2 :             (*io_err) += unref_count;
     421             : 
     422           2 :             if ( ! modify_db )
     423             :             {
     424           1 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Unlink focused features from " );
     425           1 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     426           1 :                 utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
     427             :             }
     428             :             else
     429             :             {
     430           3 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     431             :                 {
     432           2 :                     data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
     433           2 :                     data_row_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
     434           2 :                     data_err = data_database_writer_update_diagramelement_focused_feature_id ( (*this_).db_writer, diagramelement_row_id, DATA_ROW_VOID, NULL );
     435           2 :                     if ( U8_ERROR_NONE == data_err )
     436             :                     {
     437           2 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Focused features unlinked from " );
     438           2 :                         utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
     439           2 :                         utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
     440           2 :                         (*io_fix) ++;
     441             :                     }
     442             :                     else
     443             :                     {
     444           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     445           0 :                         err_result |= data_err;
     446             :                     }
     447             :                 }
     448             :             }
     449             :         }
     450             :     }
     451             :     else
     452             :     {
     453           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     454           0 :         err_result |= data_err;
     455             :     }
     456             : 
     457          30 :     U8_TRACE_END_ERR( err_result );
     458          30 :     return err_result;
     459             : }
     460             : 
     461          30 : u8_error_t ctrl_consistency_checker_private_ensure_referenced_classifiers ( ctrl_consistency_checker_t *this_,
     462             :                                                                             bool modify_db,
     463             :                                                                             uint32_t *io_err,
     464             :                                                                             uint32_t *io_fix,
     465             :                                                                             utf8stream_writer_t *out_english_report )
     466             : {
     467          30 :     U8_TRACE_BEGIN();
     468          30 :     assert ( NULL != io_err );
     469          30 :     assert ( NULL != io_fix );
     470          30 :     assert ( NULL != out_english_report );
     471          30 :     u8_error_t err_result = U8_ERROR_NONE;
     472             :     u8_error_t data_err;
     473             : 
     474             :     /* write report title */
     475          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that classifiers are referenced\n" );
     476             : 
     477             :     data_small_set_t unref;
     478          30 :     data_small_set_init( &unref );
     479          30 :     data_err = data_database_consistency_checker_find_unreferenced_classifiers ( &((*this_).db_checker), &unref );
     480          30 :     if ( U8_ERROR_NONE == data_err )
     481             :     {
     482          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     483             : 
     484          30 :         utf8stream_writer_write_str( out_english_report, "    UNREFERENCED CLASSIFIER COUNT: " );
     485          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     486          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     487             : 
     488          30 :         if ( unref_count != 0 )
     489             :         {
     490           4 :             (*io_err) += unref_count;
     491             : 
     492           4 :             if ( ! modify_db )
     493             :             {
     494           2 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Delete " );
     495           2 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     496           2 :                 utf8stream_writer_write_str( out_english_report, " classifiers.\n" );
     497             :             }
     498             :             else
     499             :             {
     500           4 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     501             :                 {
     502           2 :                     data_id_t classifier_id = data_small_set_get_id( &unref, list_pos );
     503           2 :                     data_row_t classifier_row_id = data_id_get_row_id( &classifier_id );
     504           2 :                     err_result |= data_database_consistency_checker_kill_classifier ( &((*this_).db_checker), classifier_row_id );
     505           2 :                     if ( U8_ERROR_NONE == err_result )
     506             :                     {
     507           2 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Classifier " );
     508           2 :                         utf8stream_writer_write_int( out_english_report, classifier_row_id );
     509           2 :                         utf8stream_writer_write_str( out_english_report, " deleted.\n" );
     510           2 :                         (*io_fix) ++;
     511             :                     }
     512             :                     else
     513             :                     {
     514           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     515             :                     }
     516             :                 }
     517             :             }
     518             :         }
     519             :     }
     520             :     else
     521             :     {
     522           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     523           0 :         err_result |= data_err;
     524             :     }
     525             : 
     526          30 :     U8_TRACE_END_ERR( err_result );
     527          30 :     return err_result;
     528             : }
     529             : 
     530          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_feature_parents ( ctrl_consistency_checker_t *this_,
     531             :                                                                            bool modify_db,
     532             :                                                                            uint32_t *io_err,
     533             :                                                                            uint32_t *io_fix,
     534             :                                                                            utf8stream_writer_t *out_english_report )
     535             : {
     536          30 :     U8_TRACE_BEGIN();
     537          30 :     assert ( NULL != io_err );
     538          30 :     assert ( NULL != io_fix );
     539          30 :     assert ( NULL != out_english_report );
     540          30 :     u8_error_t err_result = U8_ERROR_NONE;
     541             :     u8_error_t data_err;
     542             : 
     543             :     /* write report title */
     544          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that features have valid classifiers\n" );
     545             : 
     546             :     data_small_set_t unref;
     547          30 :     data_small_set_init( &unref );
     548          30 :     data_err = data_database_consistency_checker_find_unreferenced_features ( &((*this_).db_checker), &unref );
     549          30 :     if ( U8_ERROR_NONE == data_err )
     550             :     {
     551          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     552             : 
     553          30 :         utf8stream_writer_write_str( out_english_report, "    NONREFERENCING FEATURES COUNT: " );
     554          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     555          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     556             : 
     557          30 :         if ( unref_count != 0 )
     558             :         {
     559           3 :             (*io_err) += unref_count;
     560             : 
     561           3 :             if ( ! modify_db )
     562             :             {
     563           1 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Delete " );
     564           1 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     565           1 :                 utf8stream_writer_write_str( out_english_report, " features.\n" );
     566             :             }
     567             :             else
     568             :             {
     569           4 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     570             :                 {
     571           2 :                     data_id_t feature_id = data_small_set_get_id( &unref, list_pos );
     572           2 :                     data_row_t feature_row_id = data_id_get_row_id( &feature_id );
     573           2 :                     data_err = data_database_writer_delete_feature ( (*this_).db_writer, feature_row_id, NULL );
     574           2 :                     if ( U8_ERROR_NONE == data_err )
     575             :                     {
     576           2 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Feature " );
     577           2 :                         utf8stream_writer_write_int( out_english_report, feature_row_id );
     578           2 :                         utf8stream_writer_write_str( out_english_report, " deleted.\n" );
     579           2 :                         (*io_fix) ++;
     580             :                     }
     581             :                     else
     582             :                     {
     583           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     584           0 :                         err_result |= data_err;
     585             :                     }
     586             :                 }
     587             :             }
     588             :         }
     589             :     }
     590             :     else
     591             :     {
     592           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     593           0 :         err_result |= data_err;
     594             :     }
     595             : 
     596          30 :     U8_TRACE_END_ERR( err_result );
     597          30 :     return err_result;
     598             : }
     599             : 
     600          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_classifiers ( ctrl_consistency_checker_t *this_,
     601             :                                                                                     bool modify_db,
     602             :                                                                                     uint32_t *io_err,
     603             :                                                                                     uint32_t *io_fix,
     604             :                                                                                     utf8stream_writer_t *out_english_report )
     605             : {
     606          30 :     U8_TRACE_BEGIN();
     607          30 :     assert ( NULL != io_err );
     608          30 :     assert ( NULL != io_fix );
     609          30 :     assert ( NULL != out_english_report );
     610          30 :     u8_error_t err_result = U8_ERROR_NONE;
     611             :     u8_error_t data_err;
     612             : 
     613             :     /* write report title */
     614          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link valid classifiers\n" );
     615             : 
     616             :     data_small_set_t unref;
     617          30 :     data_small_set_init( &unref );
     618          30 :     data_err = data_database_consistency_checker_find_unreferenced_relationships ( &((*this_).db_checker), &unref );
     619          30 :     if ( U8_ERROR_NONE == data_err )
     620             :     {
     621          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     622             : 
     623          30 :         utf8stream_writer_write_str( out_english_report, "    NONREFERENCING RELATIONSHIPS COUNT: " );
     624          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     625          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     626             : 
     627          30 :         if ( unref_count != 0 )
     628             :         {
     629           3 :             (*io_err) += unref_count;
     630             : 
     631           3 :             if ( ! modify_db )
     632             :             {
     633           1 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Delete " );
     634           1 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     635           1 :                 utf8stream_writer_write_str( out_english_report, " relationships.\n" );
     636             :             }
     637             :             else
     638             :             {
     639           6 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     640             :                 {
     641           4 :                     data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
     642           4 :                     data_row_t relation_row_id = data_id_get_row_id( &relationship_id );
     643           4 :                     data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
     644           4 :                     if ( U8_ERROR_NONE == data_err )
     645             :                     {
     646           4 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Relationship " );
     647           4 :                         utf8stream_writer_write_int( out_english_report, relation_row_id );
     648           4 :                         utf8stream_writer_write_str( out_english_report, " deleted.\n" );
     649           4 :                         (*io_fix) ++;
     650             :                     }
     651             :                     else
     652             :                     {
     653           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     654           0 :                         err_result |= data_err;
     655             :                     }
     656             :                 }
     657             :             }
     658             :         }
     659             :     }
     660             :     else
     661             :     {
     662           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     663           0 :         err_result |= data_err;
     664             :     }
     665             : 
     666          30 :     U8_TRACE_END_ERR( err_result );
     667          30 :     return err_result;
     668             : }
     669             : 
     670          30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_features ( ctrl_consistency_checker_t *this_,
     671             :                                                                                  bool modify_db,
     672             :                                                                                  uint32_t *io_err,
     673             :                                                                                  uint32_t *io_fix,
     674             :                                                                                  utf8stream_writer_t *out_english_report )
     675             : {
     676          30 :     U8_TRACE_BEGIN();
     677          30 :     assert ( NULL != io_err );
     678          30 :     assert ( NULL != io_fix );
     679          30 :     assert ( NULL != out_english_report );
     680          30 :     u8_error_t err_result = U8_ERROR_NONE;
     681             :     u8_error_t data_err;
     682             : 
     683             :     /* write report title */
     684          30 :     utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link NULL or valid features\n" );
     685             : 
     686             :     data_small_set_t unref;
     687          30 :     data_small_set_init( &unref );
     688          30 :     data_err = data_database_consistency_checker_find_invalid_relationship_features ( &((*this_).db_checker), &unref );
     689          30 :     if ( U8_ERROR_NONE == data_err )
     690             :     {
     691          30 :         uint32_t unref_count = data_small_set_get_count( &unref );
     692             : 
     693          30 :         utf8stream_writer_write_str( out_english_report, "    ILLREFERENCING RELATIONSHIPS COUNT: " );
     694          30 :         utf8stream_writer_write_int( out_english_report, unref_count );
     695          30 :         utf8stream_writer_write_str( out_english_report, "\n" );
     696             : 
     697          30 :         if ( unref_count != 0 )
     698             :         {
     699           2 :             (*io_err) += unref_count;
     700             : 
     701           2 :             if ( ! modify_db )
     702             :             {
     703           1 :                 utf8stream_writer_write_str( out_english_report, "    PROPOSED FIX: Delete " );
     704           1 :                 utf8stream_writer_write_int( out_english_report, unref_count );
     705           1 :                 utf8stream_writer_write_str( out_english_report, " relationships.\n" );
     706             :             }
     707             :             else
     708             :             {
     709           4 :                 for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
     710             :                 {
     711           3 :                     data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
     712           3 :                     data_row_t relation_row_id = data_id_get_row_id( &relationship_id );
     713           3 :                     data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
     714           3 :                     if ( U8_ERROR_NONE == data_err )
     715             :                     {
     716           3 :                         utf8stream_writer_write_str( out_english_report, "    FIX: Relationship " );
     717           3 :                         utf8stream_writer_write_int( out_english_report, relation_row_id );
     718           3 :                         utf8stream_writer_write_str( out_english_report, " deleted.\n" );
     719           3 :                         (*io_fix) ++;
     720             :                     }
     721             :                     else
     722             :                     {
     723           0 :                         utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
     724           0 :                         err_result |= data_err;
     725             :                     }
     726             :                 }
     727             :             }
     728             :         }
     729             :     }
     730             :     else
     731             :     {
     732           0 :         utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
     733           0 :         err_result |= data_err;
     734             :     }
     735             : 
     736          30 :     U8_TRACE_END_ERR( err_result );
     737          30 :     return err_result;
     738             : }
     739             : 
     740             : 
     741             : /*
     742             : Copyright 2016-2024 Andreas Warnke
     743             : 
     744             : Licensed under the Apache License, Version 2.0 (the "License");
     745             : you may not use this file except in compliance with the License.
     746             : You may obtain a copy of the License at
     747             : 
     748             :     http://www.apache.org/licenses/LICENSE-2.0
     749             : 
     750             : Unless required by applicable law or agreed to in writing, software
     751             : distributed under the License is distributed on an "AS IS" BASIS,
     752             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     753             : See the License for the specific language governing permissions and
     754             : limitations under the License.
     755             : */

Generated by: LCOV version 1.16