LCOV - code coverage report
Current view: top level - gui/source - gui_search_runner.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.66.0_covts Lines: 0.0 % 202 0
Test Date: 2025-10-11 12:10:40 Functions: 0.0 % 5 0

            Line data    Source code
       1              : /* File: gui_search_runner.c; Copyright and License: see below */
       2              : 
       3              : #include "gui_search_runner.h"
       4              : #include "set/data_search_result_list.h"
       5              : #include "utf8stream/utf8stream_writer.h"
       6              : #include "u8/u8_trace.h"
       7              : #include "u8/u8_log.h"
       8              : #include "u8/u8_i32.h"
       9              : #include <assert.h>
      10              : 
      11            0 : void gui_search_runner_init ( gui_search_runner_t *this_,
      12              :                               gui_simple_message_to_user_t *message_to_user,
      13              :                               data_database_reader_t *db_reader,
      14              :                               data_database_t *database,
      15              :                               observer_t result_consumer )
      16              : {
      17            0 :     U8_TRACE_BEGIN();
      18            0 :     assert ( message_to_user != NULL );
      19            0 :     assert ( db_reader != NULL );
      20            0 :     assert ( database != NULL );
      21              : 
      22              :     /* external entities */
      23            0 :     (*this_).message_to_user = message_to_user;
      24            0 :     (*this_).db_reader = db_reader;
      25            0 :     const u8_error_t d_err = data_database_text_search_init ( &((*this_).db_searcher), database );
      26            0 :     if ( U8_ERROR_NONE != d_err )
      27              :     {
      28            0 :         U8_LOG_WARNING_HEX( "data_database_text_search_t could not be constructed.", d_err );
      29              :     }
      30            0 :     (*this_).result_consumer = result_consumer;
      31              : 
      32              :     /* request data */
      33            0 :     utf8stream_writemem_init( &((*this_).search_string_writer),
      34            0 :                               &((*this_).search_string_buf),
      35              :                               sizeof( (*this_).search_string_buf )
      36              :                             );
      37            0 :     (*this_).page_request = pos_scroll_page_new( 0, false /* backwards */ );
      38              : 
      39              :     /* result data */
      40            0 :     (*this_).result_buffer_start = 0;
      41            0 :     DATA_SEARCH_RESULT_LIST_INIT( &((*this_).result_list), (*this_).result_buffer );
      42            0 :     (*this_).result_buffer_more_after = false;
      43              : 
      44            0 :     U8_TRACE_END();
      45            0 : }
      46              : 
      47            0 : void gui_search_runner_destroy ( gui_search_runner_t *this_ )
      48              : {
      49            0 :     U8_TRACE_BEGIN();
      50              : 
      51              :     /* external entities */
      52            0 :     (*this_).message_to_user = NULL;
      53            0 :     (*this_).db_reader = NULL;
      54            0 :     const u8_error_t d_err = data_database_text_search_destroy ( &((*this_).db_searcher) );
      55            0 :     if ( U8_ERROR_NONE != d_err )
      56              :     {
      57            0 :         U8_LOG_WARNING_HEX( "data_database_text_search_t could not be destructed.", d_err );
      58              :     }
      59            0 :     observer_destroy( &((*this_).result_consumer) );
      60              : 
      61              :     /* request data */
      62            0 :     utf8stream_writemem_destroy( &((*this_).search_string_writer) );
      63              : 
      64              :     /* result data */
      65            0 :     (*this_).result_buffer_start = 0;
      66            0 :     data_search_result_list_destroy( &((*this_).result_list) );
      67            0 :     (*this_).result_buffer_more_after = false;
      68              : 
      69            0 :     U8_TRACE_END();
      70            0 : }
      71              : 
      72            0 : void gui_search_runner_run ( gui_search_runner_t *this_, const char* search_string, pos_scroll_page_t page )
      73              : {
      74            0 :     U8_TRACE_BEGIN();
      75              : 
      76            0 :     if ( search_string != NULL )
      77              :     {
      78              :         /* store parameters internally */
      79            0 :         utf8stream_writemem_reset( &((*this_).search_string_writer) );
      80            0 :         utf8stream_writer_t *write = utf8stream_writemem_get_writer( &((*this_).search_string_writer) );
      81            0 :         u8_error_t u_err = utf8stream_writer_write_str( write, search_string );
      82            0 :         if ( u_err != U8_ERROR_NONE )
      83              :         {
      84            0 :             U8_TRACE_INFO( "search string too long, was truncated." );
      85              :         }
      86              : 
      87            0 :         gui_search_runner_rerun( this_, page );
      88              :     }
      89              :     else
      90              :     {
      91            0 :         assert(false);
      92              :     }
      93              : 
      94            0 :     U8_TRACE_END();
      95            0 : }
      96              : 
      97            0 : void gui_search_runner_rerun ( gui_search_runner_t *this_, pos_scroll_page_t page )
      98              : {
      99            0 :     U8_TRACE_BEGIN();
     100              : 
     101              :     /* store parameters internally */
     102            0 :     (*this_).page_request = page;
     103            0 :     pos_scroll_page_trace( &page );
     104            0 :     const char *const search_string = utf8stream_writemem_get_string( &((*this_).search_string_writer) );
     105            0 :     uint_fast32_t skip_results
     106            0 :         = ( pos_scroll_page_get_backwards( &page ) )
     107            0 :         ? u8_i32_max2( 0, ((signed)( pos_scroll_page_get_anchor_index( &page ) - GUI_SEARCH_RUNNER_MAX_RESULTS + 1 )) )
     108            0 :         : pos_scroll_page_get_anchor_index( &page );
     109            0 :     U8_TRACE_INFO_INT( "skipping", skip_results );
     110              : 
     111              :     /* reset previous errors/warnings/infos */
     112            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     113            0 :     u8_error_t d_err = U8_ERROR_NONE;  /* a data read or data store error */
     114              : 
     115              :     /* prepare search result */
     116            0 :     (*this_).result_buffer_start = 0;
     117            0 :     data_search_result_list_clear( &((*this_).result_list) );
     118            0 :     (*this_).result_buffer_more_after = false;
     119              : 
     120              :     /* check if an id is being searched */
     121              :     data_id_t search_id;
     122            0 :     data_id_init_by_string ( &search_id, search_string );
     123            0 :     data_id_trace ( &search_id );
     124            0 :     const data_row_t search_row_id = data_id_get_row_id(&search_id);
     125              : 
     126            0 :     if ( data_id_is_valid( &search_id ))
     127              :     {
     128            0 :         switch ( data_id_get_table(&search_id) )
     129              :         {
     130            0 :             case DATA_TABLE_CLASSIFIER:
     131              :             {
     132            0 :                 d_err = data_database_reader_get_classifier_by_id( (*this_).db_reader,
     133              :                                                                    search_row_id,
     134              :                                                                    &((*this_).temp_classifier)
     135              :                                                                  );
     136            0 :                 if ( d_err == U8_ERROR_NONE )
     137              :                 {
     138              :                     data_search_result_t half_initialized;
     139            0 :                     data_search_result_init_classifier( &half_initialized,
     140              :                                                         search_row_id,
     141            0 :                                                         data_classifier_get_main_type( &((*this_).temp_classifier) ),
     142            0 :                                                         data_classifier_get_name_const( &((*this_).temp_classifier) ),
     143              :                                                         DATA_ROW_VOID /* diagram_id */
     144              :                                                       );
     145            0 :                     d_err |= gui_search_runner_private_add_diagrams_of_object( this_,
     146              :                                                                                &half_initialized,
     147              :                                                                                &skip_results
     148              :                                                                              );
     149              : 
     150            0 :                     data_classifier_destroy( &((*this_).temp_classifier) );
     151            0 :                     data_search_result_destroy( &half_initialized );
     152              :                 }
     153              :                 else
     154              :                 {
     155            0 :                     U8_TRACE_INFO( "classifier does not exist or database not open." );
     156              :                 }
     157              :             }
     158            0 :             break;
     159              : 
     160            0 :             case DATA_TABLE_FEATURE:
     161              :             {
     162            0 :                 d_err = data_database_reader_get_feature_by_id( (*this_).db_reader,
     163              :                                                                 search_row_id,
     164              :                                                                 &((*this_).temp_feature)
     165              :                                                               );
     166            0 :                 if ( d_err == U8_ERROR_NONE )
     167              :                 {
     168            0 :                     data_row_t classifier_id = data_feature_get_classifier_row_id( &((*this_).temp_feature) );
     169              :                     data_search_result_t half_initialized;
     170            0 :                     data_search_result_init_feature( &half_initialized,
     171            0 :                                                      data_feature_get_row_id( &((*this_).temp_feature) ),
     172            0 :                                                      data_feature_get_main_type( &((*this_).temp_feature) ),
     173            0 :                                                      data_feature_get_key_const( &((*this_).temp_feature) ),
     174              :                                                      classifier_id,
     175              :                                                      DATA_ROW_VOID /* diagram_id */
     176              :                                                    );
     177            0 :                     d_err |= gui_search_runner_private_add_diagrams_of_object( this_,
     178              :                                                                                &half_initialized,
     179              :                                                                                &skip_results
     180              :                                                                              );
     181              : 
     182            0 :                     data_feature_destroy( &((*this_).temp_feature) );
     183            0 :                     data_search_result_destroy( &half_initialized );
     184              :                 }
     185              :                 else
     186              :                 {
     187            0 :                     U8_TRACE_INFO( "feature does not exist or database not open." );
     188              :                 }
     189              :             }
     190            0 :             break;
     191              : 
     192            0 :             case DATA_TABLE_RELATIONSHIP:
     193              :             {
     194            0 :                 d_err = data_database_reader_get_relationship_by_id( (*this_).db_reader,
     195              :                                                                      search_row_id,
     196              :                                                                      &((*this_).temp_relationship)
     197              :                                                                    );
     198            0 :                 if ( d_err == U8_ERROR_NONE )
     199              :                 {
     200            0 :                     data_row_t classifier_id = data_relationship_get_from_classifier_row_id( &((*this_).temp_relationship) );
     201              :                     data_search_result_t half_initialized;
     202            0 :                     data_search_result_init_relationship( &half_initialized,
     203            0 :                                                           data_relationship_get_row_id( &((*this_).temp_relationship) ),
     204            0 :                                                           data_relationship_get_main_type( &((*this_).temp_relationship) ),
     205            0 :                                                           data_relationship_get_name_const( &((*this_).temp_relationship) ),
     206              :                                                           classifier_id,
     207            0 :                                                           data_relationship_get_to_classifier_row_id( &((*this_).temp_relationship) ),
     208              :                                                           DATA_ROW_VOID /* diagram_id */
     209              :                                                         );
     210            0 :                     d_err |= gui_search_runner_private_add_diagrams_of_object( this_,
     211              :                                                                                &half_initialized,
     212              :                                                                                &skip_results
     213              :                                                                              );
     214              : 
     215            0 :                     data_relationship_destroy( &((*this_).temp_relationship) );
     216            0 :                     data_search_result_destroy( &half_initialized );
     217              :                 }
     218              :                 else
     219              :                 {
     220            0 :                     U8_TRACE_INFO( "relationship does not exist or database not open." );
     221              :                 }
     222              :             }
     223            0 :             break;
     224              : 
     225            0 :             case DATA_TABLE_DIAGRAMELEMENT:
     226              :             {
     227            0 :                 d_err = data_database_reader_get_diagramelement_by_id( (*this_).db_reader,
     228              :                                                                        search_row_id,
     229              :                                                                        &((*this_).temp_diagramelement)
     230              :                                                                      );
     231            0 :                 if ( d_err == U8_ERROR_NONE )
     232              :                 {
     233            0 :                     if ( skip_results == 0 )
     234              :                     {
     235              :                         data_search_result_t half_initialized;
     236            0 :                         data_search_result_init_classifier( &half_initialized,
     237            0 :                                                             data_diagramelement_get_classifier_row_id(&((*this_).temp_diagramelement)),
     238              :                                                             0 /* match_type is unknown */,
     239              :                                                             "" /* match_name */,
     240            0 :                                                             data_diagramelement_get_diagram_row_id(&((*this_).temp_diagramelement))
     241              :                                                           );
     242            0 :                         const u8_error_t err = data_search_result_list_add( &((*this_).result_list), &half_initialized );
     243            0 :                         if ( err != U8_ERROR_NONE )
     244              :                         {
     245            0 :                             d_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
     246            0 :                             U8_LOG_ANOMALY( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at inserting search result to list" );
     247            0 :                             (*this_).result_buffer_more_after = true;  /* there are more results that cannot be stored in &((*this_).result_list) */
     248              :                         }
     249            0 :                         data_search_result_destroy( &half_initialized );
     250              :                     }
     251              :                     else
     252              :                     {
     253              :                         /* to advance to the requested search result page, skip this entry */
     254            0 :                         skip_results --;
     255            0 :                         (*this_).result_buffer_start ++;
     256              :                     }
     257              : 
     258            0 :                     data_diagramelement_destroy( &((*this_).temp_diagramelement) );
     259              :                 }
     260              :                 else
     261              :                 {
     262            0 :                     U8_TRACE_INFO( "diagramelement does not exist or database not open." );
     263              :                 }
     264              :             }
     265            0 :             break;
     266              : 
     267            0 :             case DATA_TABLE_DIAGRAM:
     268              :             {
     269            0 :                 d_err = data_database_reader_get_diagram_by_id ( (*this_).db_reader, search_row_id, &((*this_).temp_diagram) );
     270            0 :                 if ( d_err == U8_ERROR_NONE )
     271              :                 {
     272            0 :                     if ( skip_results == 0 )
     273              :                     {
     274              :                         data_search_result_t half_initialized;
     275            0 :                         data_search_result_init_diagram( &half_initialized,
     276              :                                                          search_row_id,
     277            0 :                                                          data_diagram_get_diagram_type( &((*this_).temp_diagram) ),
     278            0 :                                                          data_diagram_get_name_const( &((*this_).temp_diagram) )
     279              :                                                        );
     280            0 :                         const u8_error_t err = data_search_result_list_add( &((*this_).result_list), &half_initialized );
     281            0 :                         if ( err != U8_ERROR_NONE )
     282              :                         {
     283            0 :                             d_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
     284            0 :                             U8_LOG_ANOMALY( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at inserting search result to list" );
     285            0 :                             (*this_).result_buffer_more_after = true;  /* there are more results that cannot be stored in &((*this_).result_list) */
     286              :                         }
     287            0 :                         data_search_result_destroy( &half_initialized );
     288              :                     }
     289              :                     else
     290              :                     {
     291              :                         /* to advance to the requested search result page, skip this entry */
     292            0 :                         skip_results --;
     293            0 :                         (*this_).result_buffer_start ++;
     294              :                     }
     295              : 
     296            0 :                     data_diagram_destroy( &((*this_).temp_diagram) );
     297              :                 }
     298              :                 else
     299              :                 {
     300            0 :                     U8_TRACE_INFO( "diagram does not exist or database not open." );
     301              :                 }
     302              :             }
     303            0 :             break;
     304              : 
     305            0 :             default:
     306              :             {
     307            0 :                 assert(false);  /* data_id_is_valid should have been false already */
     308              :             }
     309              :             break;
     310              :         }
     311              :     }
     312              :     else
     313              :     {
     314            0 :         U8_LOG_EVENT_STR( "User search input is not an id", search_string );
     315              :     }
     316              : 
     317              :     /* free text search */
     318            0 :     if ( d_err == U8_ERROR_NONE )
     319              :     {
     320              :         data_search_result_iterator_t data_search_result_iterator;
     321            0 :         d_err |= data_search_result_iterator_init_empty( &data_search_result_iterator );
     322            0 :         d_err = data_database_text_search_get_objects_by_text_fragment( &((*this_).db_searcher),
     323              :                                                                         search_string,
     324              :                                                                         &data_search_result_iterator
     325              :                                                                       );
     326            0 :         while (( data_search_result_iterator_has_next( &data_search_result_iterator ) )&&( d_err == U8_ERROR_NONE ))
     327              :         {
     328              :             data_search_result_t current_search_result;
     329            0 :             d_err |= data_search_result_iterator_next( &data_search_result_iterator,
     330              :                                                        &current_search_result
     331              :                                                      );
     332            0 :             if ( skip_results == 0 )
     333              :             {
     334            0 :                 const u8_error_t err = data_search_result_list_add( &((*this_).result_list), &current_search_result );
     335            0 :                 if ( err != U8_ERROR_NONE )
     336              :                 {
     337            0 :                     d_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
     338            0 :                     U8_LOG_ANOMALY( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at inserting search result to list" );
     339            0 :                     (*this_).result_buffer_more_after = true;  /* there are more results that cannot be stored in &((*this_).result_list) */
     340              :                 }
     341              :             }
     342              :             else
     343              :             {
     344              :                 /* to advance to the requested search result page, skip this entry */
     345            0 :                 skip_results --;
     346            0 :                 (*this_).result_buffer_start ++;
     347              :             }
     348              :         }
     349            0 :         d_err |= data_search_result_iterator_destroy( &data_search_result_iterator );
     350              :     }
     351              : 
     352            0 :     if ( d_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED )
     353              :     {
     354              :         /* it is rather expected than a real error that the result list gets full */
     355            0 :         U8_TRACE_INFO( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at inserting search result to list" );
     356              :     }
     357            0 :     else if ( U8_ERROR_NONE != d_err )
     358              :     {
     359            0 :         U8_LOG_ERROR_HEX( "data_database_text_search_t could not search.", d_err );
     360              :     }
     361              : 
     362              :     /* present the result */
     363            0 :     observer_notify( &((*this_).result_consumer), this_ );
     364              : 
     365              :     /* clear the result (the notification above is synchronous, the search results are already processed.) */
     366            0 :     data_search_result_list_clear( &((*this_).result_list) );
     367              : 
     368            0 :     U8_TRACE_END();
     369            0 : }
     370              : 
     371            0 : u8_error_t gui_search_runner_private_add_diagrams_of_object( gui_search_runner_t *this_,
     372              :                                                              data_search_result_t *result_template,
     373              :                                                              uint_fast32_t *io_skip_results
     374              :                                                            )
     375              : {
     376            0 :     U8_TRACE_BEGIN();
     377            0 :     assert( result_template != NULL );
     378            0 :     u8_error_t d_err = U8_ERROR_NONE;  /* a data read or data store error */
     379              : 
     380              :     /* initialize an iterator to fetch all diagrams where result_template occurs: */
     381              :     data_diagram_iterator_t diagram_iterator;
     382            0 :     d_err |= data_diagram_iterator_init_empty( &diagram_iterator );
     383            0 :     const data_table_t object_type = data_id_get_table( data_search_result_get_match_id_const( result_template ));
     384            0 :     switch ( object_type )
     385              :     {
     386            0 :         case DATA_TABLE_CLASSIFIER:
     387              :         {
     388              :             const data_row_t classifier_row_id
     389            0 :                 = data_id_get_row_id( data_search_result_get_match_id_const( result_template ));
     390            0 :             d_err |= data_database_reader_get_diagrams_by_classifier_id( (*this_).db_reader,
     391              :                                                                          classifier_row_id,
     392              :                                                                          &diagram_iterator
     393              :                                                                        );
     394              :         }
     395            0 :         break;
     396              : 
     397            0 :         case DATA_TABLE_FEATURE:
     398              :         {
     399              :             const data_row_t classifier_row_id
     400            0 :                 = data_id_get_row_id( data_search_result_get_src_classifier_id_const( result_template ));
     401            0 :             d_err |= data_database_reader_get_diagrams_by_classifier_id( (*this_).db_reader,
     402              :                                                                          classifier_row_id,
     403              :                                                                          &diagram_iterator
     404              :                                                                        );
     405              :         }
     406            0 :         break;
     407              : 
     408            0 :         case DATA_TABLE_RELATIONSHIP:
     409              :         {
     410              :             const data_row_t relationship_row_id
     411            0 :                 = data_id_get_row_id( data_search_result_get_match_id_const( result_template ));
     412            0 :             d_err |= data_database_reader_get_diagrams_by_relationship_id( (*this_).db_reader,
     413              :                                                                            relationship_row_id,
     414              :                                                                            &diagram_iterator
     415              :                                                                          );
     416              :         }
     417            0 :         break;
     418              : 
     419            0 :         default:
     420              :         {
     421            0 :             U8_LOG_ERROR_INT( "gui_search_runner_private_add_diagrams_of_object called with search result of wrong type:",
     422              :                              object_type
     423              :                            );
     424            0 :             assert(false);
     425              :         }
     426              :         break;
     427              :     }
     428              : 
     429            0 :     while (( data_diagram_iterator_has_next( &diagram_iterator ) )&&( d_err == U8_ERROR_NONE ))
     430              :     {
     431              :         /* fetch diagram from iterator */
     432            0 :         d_err |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram) );
     433            0 :         const data_row_t diagram_row_id = data_diagram_get_row_id( &((*this_).temp_diagram) );
     434              : 
     435            0 :         if ( (*io_skip_results) == 0 )
     436              :         {
     437              :             /* complete the half initialized search result template */
     438            0 :             data_id_reinit( data_search_result_get_diagram_id_ptr( result_template ), DATA_TABLE_DIAGRAM, diagram_row_id );
     439              : 
     440            0 :             const u8_error_t err = data_search_result_list_add( &((*this_).result_list), result_template );
     441            0 :             if ( err != U8_ERROR_NONE )
     442              :             {
     443            0 :                 d_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
     444            0 :                 U8_LOG_ANOMALY( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at inserting search result to list" );
     445            0 :                 (*this_).result_buffer_more_after = true;  /* there are more results that cannot be stored in &((*this_).result_list) */
     446              :             }
     447              :         }
     448              :         else
     449              :         {
     450              :             /* to advance to the requested search result page, skip this entry */
     451            0 :             *io_skip_results = (*io_skip_results) - 1;
     452            0 :             (*this_).result_buffer_start ++;
     453              :         }
     454              : 
     455            0 :         data_diagram_destroy( &((*this_).temp_diagram) );
     456              :     }
     457              : 
     458            0 :     d_err |= data_diagram_iterator_destroy( &diagram_iterator );
     459              : 
     460            0 :     U8_TRACE_END_ERR( d_err );
     461            0 :     return d_err;
     462              : }
     463              : 
     464              : 
     465              : /*
     466              : Copyright 2020-2025 Andreas Warnke
     467              : 
     468              : Licensed under the Apache License, Version 2.0 (the "License");
     469              : you may not use this file except in compliance with the License.
     470              : You may obtain a copy of the License at
     471              : 
     472              :     http://www.apache.org/licenses/LICENSE-2.0
     473              : 
     474              : Unless required by applicable law or agreed to in writing, software
     475              : distributed under the License is distributed on an "AS IS" BASIS,
     476              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     477              : See the License for the specific language governing permissions and
     478              : limitations under the License.
     479              : */
        

Generated by: LCOV version 2.0-1