LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_drop_invisibles.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 95.6 % 90 86
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /* File: consistency_drop_invisibles.c; Copyright and License: see below */
       2              : 
       3              : #include "consistency/consistency_drop_invisibles.h"
       4              : #include "ctrl_classifier_controller.h"
       5              : #include "ctrl_diagram_controller.h"
       6              : #include "u8/u8_trace.h"
       7              : #include "u8/u8_log.h"
       8              : 
       9           42 : void consistency_drop_invisibles_init( consistency_drop_invisibles_t *this_,
      10              :                                        data_database_reader_t *db_reader,
      11              :                                        struct ctrl_classifier_controller_struct *clfy_ctrl,
      12              :                                        struct ctrl_diagram_controller_struct *diag_ctrl )
      13              : {
      14           42 :     U8_TRACE_BEGIN();
      15           42 :     assert( NULL != db_reader );
      16           42 :     assert( NULL != clfy_ctrl );
      17           42 :     assert( NULL != diag_ctrl );
      18              : 
      19           42 :     (*this_).db_reader = db_reader;
      20           42 :     (*this_).clfy_ctrl = clfy_ctrl;
      21           42 :     (*this_).diag_ctrl = diag_ctrl;
      22              : 
      23           42 :     U8_TRACE_END();
      24           42 : }
      25              : 
      26           42 : void consistency_drop_invisibles_destroy( consistency_drop_invisibles_t *this_ )
      27              : {
      28           42 :     U8_TRACE_BEGIN();
      29              : 
      30           42 :     (*this_).db_reader = NULL;
      31           42 :     (*this_).clfy_ctrl = NULL;
      32           42 :     (*this_).diag_ctrl = NULL;
      33              : 
      34           42 :     U8_TRACE_END();
      35           42 : }
      36              : 
      37              : /* ================================ NO ABANDONED CLASSIFIERS ================================ */
      38              : 
      39            5 : u8_error_t consistency_drop_invisibles_delete_unreferenced_classifier( consistency_drop_invisibles_t *this_,
      40              :                                                                        const data_diagramelement_t *deleted_diagramelement )
      41              : {
      42            5 :     U8_TRACE_BEGIN();
      43            5 :     assert( NULL != deleted_diagramelement );
      44            5 :     u8_error_t result = U8_ERROR_NONE;
      45              : 
      46              :     /* try to also delete the classifier, ignore errors because it is ok if the classifier is still referenced */
      47              :     u8_error_t my_ctrl_result;
      48              : 
      49            5 :     my_ctrl_result = ctrl_classifier_controller_delete_classifier( (*this_).clfy_ctrl,
      50              :                                                                    data_diagramelement_get_classifier_row_id( deleted_diagramelement ),
      51              :                                                                    CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
      52              :                                                                  );
      53              : 
      54            5 :     if ( u8_error_contains( my_ctrl_result, U8_ERROR_OBJECT_STILL_REFERENCED ) )
      55              :     {
      56            3 :         U8_LOG_EVENT( "The classifier cannot be deleted because it is still referenced." );
      57              :     }
      58              :     else
      59              :     {
      60              :         /* report this unexpected error */
      61            2 :         result |= my_ctrl_result;
      62              :     }
      63              : 
      64            5 :     U8_TRACE_END_ERR( result );
      65            5 :     return result;
      66              : }
      67              : 
      68              : /* ================================ NO INVISIBLE RELATIONSHIPS ================================ */
      69              : 
      70            5 : u8_error_t consistency_drop_invisibles_delete_invisible_relationships( consistency_drop_invisibles_t *this_,
      71              :                                                                        const data_diagramelement_t *deleted_diagramelement )
      72              : {
      73            5 :     U8_TRACE_BEGIN();
      74            5 :     assert( NULL != deleted_diagramelement );
      75            5 :     u8_error_t result = U8_ERROR_NONE;
      76              : 
      77            5 :     data_row_t classifier_id = data_diagramelement_get_classifier_row_id( deleted_diagramelement );
      78              :     data_small_set_t relations_to_delete;
      79            5 :     data_small_set_init( &relations_to_delete );
      80              : 
      81              :     /* load relationships to be checked */
      82              :     data_relationship_iterator_t relationship_iterator;
      83            5 :     result |= data_relationship_iterator_init_empty( &relationship_iterator );
      84            5 :     result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
      85              :                                                                        classifier_id,
      86              :                                                                        &relationship_iterator
      87              :                                                                      );
      88            5 :     if ( result == U8_ERROR_NONE )
      89              :     {
      90            7 :         while( data_relationship_iterator_has_next( &relationship_iterator ) )
      91              :         {
      92            2 :             result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship_buf) );
      93              : 
      94            2 :             bool visible = true;
      95              :             const u8_error_t vis_err
      96            2 :                 = consistency_drop_invisibles_private_has_relationship_a_diagram( this_, &((*this_).temp_relationship_buf), &visible );
      97              : 
      98            2 :             if ( vis_err == U8_ERROR_NONE )
      99              :             {
     100            2 :                 if ( ! visible )
     101              :                 {
     102              :                     /* invisible relationship found */
     103              :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
     104            1 :                     const data_id_t relation_to_delete = data_relationship_get_data_id( &((*this_).temp_relationship_buf) );
     105            1 :                     result |= data_small_set_add_obj( &relations_to_delete, relation_to_delete );
     106              :                 }
     107              :             }
     108              :             else
     109              :             {
     110            0 :                 result |= vis_err;
     111              :             }
     112              :         }
     113              :     }
     114              :     else
     115              :     {
     116            0 :         U8_LOG_WARNING( "Relationships of the deleted classifier cannot be checked for being superfluous now." );
     117            0 :         U8_TRACE_INFO_INT( "classifier has unckecked relationships:", classifier_id );
     118              :     }
     119            5 :     result |= data_relationship_iterator_destroy( &relationship_iterator );
     120              :     /* note that relationship_iterator cannot be used here any longer due to re-entrancy by recursion */
     121              : 
     122              :     /* delete all found relationship */
     123            5 :     const uint32_t relations_count = data_small_set_get_count( &relations_to_delete );
     124            6 :     for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ )
     125              :     {
     126            1 :         const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 );
     127            1 :         assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP );
     128            1 :         result |= ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl,
     129              :                                                                   data_id_get_row_id( &delete_rel ),
     130              :                                                                   CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
     131              :                                                                 );
     132              :     }
     133              : 
     134            5 :     data_small_set_destroy( &relations_to_delete );
     135              : 
     136            5 :     U8_TRACE_END_ERR( result );
     137            5 :     return result;
     138              : }
     139              : 
     140            2 : u8_error_t consistency_drop_invisibles_private_has_relationship_a_diagram( consistency_drop_invisibles_t *this_,
     141              :                                                                            const data_relationship_t *relation,
     142              :                                                                            bool *out_result )
     143              : {
     144            2 :     U8_TRACE_BEGIN();
     145            2 :     assert( NULL != relation );
     146            2 :     assert( NULL != out_result );
     147            2 :     u8_error_t result = U8_ERROR_NONE;
     148              : 
     149            2 :     const data_row_t from_classifier_id = data_relationship_get_from_classifier_row_id( relation );
     150            2 :     const data_row_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation );
     151              : 
     152            2 :     if ( from_classifier_id == to_classifier_id )
     153              :     {
     154              :         /* relationship is visible in one diagram because source and destination are identical */
     155            0 :         *out_result = true;
     156              :     }
     157              :     else
     158              :     {
     159            2 :         bool same_diag = false;
     160              :         data_small_set_t from_diagrams;
     161            2 :         data_small_set_init( &from_diagrams );
     162              : 
     163              :         /* load diagramelements that are referenced by the relationships from end */
     164              :         {
     165              :             data_diagramelement_iterator_t diagramelement_iterator;
     166            2 :             result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator );
     167            2 :             result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
     168              :                                                                                  from_classifier_id,
     169              :                                                                                  &diagramelement_iterator
     170              :                                                                                );
     171            2 :             if ( result == U8_ERROR_NONE )
     172              :             {
     173            4 :                 while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
     174              :                 {
     175            2 :                     result |= data_diagramelement_iterator_next( &diagramelement_iterator, &((*this_).temp_diagelement_buf) );
     176              :                     const data_id_t from_diag_id
     177            2 :                         = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) );
     178              :                     const u8_error_t ins_err
     179            2 :                         = data_small_set_add_obj( &from_diagrams, from_diag_id );
     180            2 :                     if ( ins_err == U8_ERROR_DUPLICATE_ID )
     181              :                     {
     182              :                         /* not an error */
     183              :                     }
     184              :                     else
     185              :                     {
     186            2 :                         result |= ins_err;
     187              :                     }
     188              :                 }
     189              :             }
     190            2 :             result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
     191              :         }
     192              : 
     193              :         /* load diagramelements that are referenced by the relationships to end */
     194              :         data_diagramelement_iterator_t diagramelement_iterator2;
     195            2 :         result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator2 );
     196            2 :         result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
     197              :                                                                              to_classifier_id,
     198              :                                                                              &diagramelement_iterator2
     199              :                                                                            );
     200              : 
     201              :         /* check for same diagram */
     202            2 :         if ( result == U8_ERROR_NONE )
     203              :         {
     204            5 :             while ( data_diagramelement_iterator_has_next( &diagramelement_iterator2 ) )
     205              :             {
     206            3 :                 result |= data_diagramelement_iterator_next( &diagramelement_iterator2, &((*this_).temp_diagelement_buf) );
     207              :                 const data_id_t to_diag_id
     208            3 :                     = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) );
     209            3 :                 if ( data_small_set_contains( &from_diagrams, to_diag_id ) )
     210              :                 {
     211            1 :                     same_diag = true;
     212              :                 }
     213              :             }
     214              :         }
     215            2 :         result |= data_diagramelement_iterator_destroy( &diagramelement_iterator2 );
     216            2 :         data_small_set_destroy( &from_diagrams );
     217              : 
     218            2 :         *out_result = same_diag;
     219              :     }
     220              : 
     221            2 :     U8_TRACE_END_ERR( result );
     222            2 :     return result;
     223              : }
     224              : 
     225              : 
     226              : /*
     227              : Copyright 2018-2025 Andreas Warnke
     228              : 
     229              : Licensed under the Apache License, Version 2.0 (the "License");
     230              : you may not use this file except in compliance with the License.
     231              : You may obtain a copy of the License at
     232              : 
     233              :     http://www.apache.org/licenses/LICENSE-2.0
     234              : 
     235              : Unless required by applicable law or agreed to in writing, software
     236              : distributed under the License is distributed on an "AS IS" BASIS,
     237              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     238              : See the License for the specific language governing permissions and
     239              : limitations under the License.
     240              : */
        

Generated by: LCOV version 2.0-1