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.61.0_covts Lines: 87 95 91.6 %
Date: 2024-10-26 21:44:38 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_id_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           5 :     uint32_t relationship_count = 0;
      83             :     const u8_error_t d_err
      84           5 :         = data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
      85             :                                                                    classifier_id,
      86             :                                                                    CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_RELATIONS,
      87           5 :                                                                    &((*this_).private_temp_rel_buf),
      88             :                                                                    &relationship_count
      89             :                                                                  );
      90           5 :     if ( d_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED )
      91             :     {
      92           0 :         U8_LOG_ANOMALY( "The dereferenced classifier has more relationships than can be checked for being superfluous now." );
      93           0 :         U8_TRACE_INFO_INT( "classifier has too many relationships:", classifier_id );
      94             :         /* no further error propagation. */
      95             :     }
      96             :     else
      97             :     {
      98           5 :         result |= d_err;
      99             :     }
     100             : 
     101           5 :     if ( result == U8_ERROR_NONE )
     102             :     {
     103           7 :         for ( uint_fast32_t rel_idx = 0; rel_idx < relationship_count; rel_idx ++ )
     104             :         {
     105           2 :             const data_relationship_t *relation = &((*this_).private_temp_rel_buf[rel_idx]);
     106             : 
     107           2 :             bool visible = true;
     108             :             const u8_error_t vis_err
     109           2 :                 = consistency_drop_invisibles_private_has_relationship_a_diagram( this_, relation, &visible );
     110             : 
     111           2 :             if ( vis_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED )
     112             :             {
     113           0 :                 U8_LOG_ANOMALY( "A relationship is connected to a classifier that is too often referenced to check for being superfluous now." );
     114           0 :                 U8_TRACE_INFO_INT( "classifier or related classifier has too many diagramelements:", classifier_id );
     115             :                 /* no further error propagation. */
     116             :             }
     117           2 :             else if ( vis_err == U8_ERROR_NONE )
     118             :             {
     119           2 :                 if ( ! visible )
     120             :                 {
     121             :                     /* invisible relationship found */
     122             :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
     123           1 :                     result |= data_small_set_add_obj( &relations_to_delete, data_relationship_get_data_id( relation ) );
     124             :                 }
     125             :             }
     126             :             else
     127             :             {
     128           0 :                 result |= vis_err;
     129             :             }
     130             :         }
     131             :     }
     132             : 
     133             :     /* delete all found relationship */
     134             :     /* note that (*this_).private_temp_rel_buf cannot be used here any longer due to re-entrancy by recursion */
     135           5 :     const uint32_t relations_count = data_small_set_get_count( &relations_to_delete );
     136           6 :     for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ )
     137             :     {
     138           1 :         const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 );
     139           1 :         assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP );
     140           1 :         result |= ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl,
     141             :                                                                   data_id_get_row_id( &delete_rel ),
     142             :                                                                   CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
     143             :                                                                 );
     144             :     }
     145             : 
     146           5 :     data_small_set_destroy( &relations_to_delete );
     147             : 
     148           5 :     U8_TRACE_END_ERR( result );
     149           5 :     return result;
     150             : }
     151             : 
     152           2 : u8_error_t consistency_drop_invisibles_private_has_relationship_a_diagram( consistency_drop_invisibles_t *this_,
     153             :                                                                            const data_relationship_t *relation,
     154             :                                                                            bool *out_result )
     155             : {
     156           2 :     U8_TRACE_BEGIN();
     157           2 :     assert( NULL != relation );
     158           2 :     assert( NULL != out_result );
     159           2 :     u8_error_t result = U8_ERROR_NONE;
     160             : 
     161           2 :     const data_row_id_t from_classifier_id = data_relationship_get_from_classifier_row_id( relation );
     162           2 :     const data_row_id_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation );
     163             : 
     164           2 :     if ( from_classifier_id == to_classifier_id )
     165             :     {
     166             :         /* relationship is visible in one diagram because source and destination are identical */
     167           0 :         *out_result = true;
     168             :     }
     169             :     else
     170             :     {
     171             :         data_small_set_t from_diagrams;
     172           2 :         data_small_set_init( &from_diagrams );
     173             :         u8_error_t from_err;
     174             : 
     175             :         /* load diagramelements that are referenced by the relationships from end */
     176             :         {
     177           2 :             uint32_t from_diagramelement_count = 0;
     178             :             from_err
     179           2 :                 = data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
     180             :                                                                              from_classifier_id,
     181             :                                                                              CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_DIAGELES,
     182           2 :                                                                              &((*this_).private_temp_diagele_buf),
     183             :                                                                              &from_diagramelement_count
     184             :                                                                            );
     185           2 :             if ( from_err == U8_ERROR_NONE )
     186             :             {
     187             :                 /* copy diagram ids to id-set */
     188           4 :                 for ( uint_fast32_t from_idx = 0; from_idx < from_diagramelement_count; from_idx ++ )
     189             :                 {
     190             :                     const data_id_t from_diag_id
     191           2 :                         = data_diagramelement_get_diagram_data_id ( &((*this_).private_temp_diagele_buf[from_idx]) );
     192             :                     const u8_error_t ins_err
     193           2 :                         = data_small_set_add_obj( &from_diagrams, from_diag_id );
     194           2 :                     if ( ins_err == U8_ERROR_DUPLICATE_ID )
     195             :                     {
     196             :                         /* not an error */
     197             :                     }
     198             :                     else
     199             :                     {
     200           2 :                         from_err |= ins_err;
     201             :                     }
     202             :                 }
     203             :             }
     204             :         }
     205             : 
     206             :         /* load diagramelements that are referenced by the relationships to end */
     207           2 :         uint32_t to_diagramelement_count = 0;
     208             :         const u8_error_t to_err
     209           2 :             = data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
     210             :                                                                          to_classifier_id,
     211             :                                                                          CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_DIAGELES,
     212           2 :                                                                          &((*this_).private_temp_diagele_buf),
     213             :                                                                          &to_diagramelement_count
     214             :                                                                        );
     215             : 
     216             :         /* check for same diagram */
     217           2 :         if (( from_err == U8_ERROR_NONE )&&( to_err == U8_ERROR_NONE ))
     218           2 :         {
     219           2 :             bool same_diag = false;
     220           5 :             for ( uint_fast32_t to_idx = 0; to_idx < to_diagramelement_count; to_idx ++ )
     221             :             {
     222             :                 const data_id_t to_diag_id
     223           3 :                     = data_diagramelement_get_diagram_data_id ( &((*this_).private_temp_diagele_buf[to_idx]) );
     224           3 :                 if ( data_small_set_contains( &from_diagrams, to_diag_id ) )
     225             :                 {
     226           1 :                     same_diag = true;
     227             :                 }
     228             :             }
     229           2 :             *out_result = same_diag;
     230             :         }
     231             :         else
     232             :         {
     233           0 :             result |= from_err;
     234           0 :             result |= to_err;
     235             :         }
     236             : 
     237           2 :         data_small_set_destroy( &from_diagrams );
     238             :     }
     239             : 
     240           2 :     U8_TRACE_END_ERR( result );
     241           2 :     return result;
     242             : }
     243             : 
     244             : 
     245             : /*
     246             : Copyright 2018-2024 Andreas Warnke
     247             : 
     248             : Licensed under the Apache License, Version 2.0 (the "License");
     249             : you may not use this file except in compliance with the License.
     250             : You may obtain a copy of the License at
     251             : 
     252             :     http://www.apache.org/licenses/LICENSE-2.0
     253             : 
     254             : Unless required by applicable law or agreed to in writing, software
     255             : distributed under the License is distributed on an "AS IS" BASIS,
     256             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     257             : See the License for the specific language governing permissions and
     258             : limitations under the License.
     259             : */

Generated by: LCOV version 1.16