LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_drop_invisibles.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 86 90 95.6 %
Date: 2024-12-21 18:34:41 Functions: 5 5 100.0 %

          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-2024 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 1.16