LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_relationship.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.2_covts Lines: 100.0 % 94 94
Test Date: 2026-05-03 11:56:31 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /* File: consistency_relationship.c; Copyright and License: see below */
       2              : 
       3              : #include "consistency/consistency_relationship.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           47 : void consistency_relationship_init( consistency_relationship_t *this_,
      10              :                                     data_database_reader_t *db_reader,
      11              :                                     struct ctrl_classifier_controller_struct *clfy_ctrl )
      12              : {
      13           47 :     U8_TRACE_BEGIN();
      14           47 :     assert( NULL != db_reader );
      15           47 :     assert( NULL != clfy_ctrl );
      16              : 
      17           47 :     (*this_).db_reader = db_reader;
      18           47 :     (*this_).clfy_ctrl = clfy_ctrl;
      19           47 :     data_rules_init( &((*this_).rules) );
      20              : 
      21           47 :     U8_TRACE_END();
      22           47 : }
      23              : 
      24           47 : void consistency_relationship_destroy( consistency_relationship_t *this_ )
      25              : {
      26           47 :     U8_TRACE_BEGIN();
      27              : 
      28           47 :     (*this_).db_reader = NULL;
      29           47 :     (*this_).clfy_ctrl = NULL;
      30           47 :     data_rules_destroy( &((*this_).rules) );
      31              : 
      32           47 :     U8_TRACE_END();
      33           47 : }
      34              : 
      35            9 : u8_error_t consistency_relationship_delete_invisibles_in_diagram( consistency_relationship_t *this_,
      36              :                                                                   const data_diagram_t *updated_diagram,
      37              :                                                                   int32_t * out_deleted_relationships )
      38              : {
      39            9 :     U8_TRACE_BEGIN();
      40            9 :     assert( updated_diagram != NULL );
      41            9 :     assert( out_deleted_relationships != NULL );
      42            9 :     u8_error_t result = U8_ERROR_NONE;
      43              : 
      44            9 :     const data_diagram_type_t new_diagram_type = data_diagram_get_diagram_type( updated_diagram );
      45            9 :     const bool new_diagram_shows_rel = data_rules_diagram_shows_uncond_relationships( &((*this_).rules), new_diagram_type );
      46              :     /*
      47              :     const bool new_diagram_is_scenario = data_rules_diagram_is_scenario( &((*this_).rules), new_diagram_type );
      48              :     const bool new_diagram_shows_msg = data_rules_diagram_shows_scenario_relationships( &((*this_).rules), new_diagram_type );
      49              :     assert( new_diagram_is_scenario == new_diagram_shows_msg );
      50              :     */
      51              : 
      52            9 :     if ( ! new_diagram_shows_rel )
      53              :     {
      54            6 :         *out_deleted_relationships = 0;
      55            6 :         const data_row_t diagram_id = data_diagram_get_row( updated_diagram );
      56              :         data_diagramelement_iterator_t diagramelement_iterator;
      57            6 :         data_diagramelement_iterator_init_empty( &diagramelement_iterator );
      58            6 :         result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
      59              :                                                                           diagram_id,
      60              :                                                                           &diagramelement_iterator
      61              :                                                                         );
      62            6 :         if ( result == U8_ERROR_NONE )
      63              :         {
      64           15 :             while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
      65              :             {
      66              :                 data_diagramelement_t diagelement_buf;
      67            9 :                 result |= data_diagramelement_iterator_next( &diagramelement_iterator, &diagelement_buf );
      68            9 :                 const data_row_t classifier_id = data_diagramelement_get_classifier_row( &diagelement_buf );
      69              :                 int32_t deleted_relationships;
      70            9 :                 result |= consistency_relationship_delete_invisibles_at_classifier( this_, classifier_id, &deleted_relationships );
      71            9 :                 *out_deleted_relationships += deleted_relationships;
      72              :             }
      73              :         }
      74            6 :         result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
      75              :     }
      76              :     else
      77              :     {
      78            3 :         U8_TRACE_INFO("All unconditional relationships are visible, no need to check for invisibility.");
      79            3 :         *out_deleted_relationships = 0;
      80              :     }
      81              : 
      82            9 :     U8_TRACE_END_ERR( result );
      83            9 :     return result;
      84              : }
      85              : 
      86           37 : u8_error_t consistency_relationship_delete_invisibles_at_classifier( consistency_relationship_t *this_,
      87              :                                                                      data_row_t classifier_id,
      88              :                                                                      int32_t * out_deleted_relationships )
      89              : {
      90           37 :     U8_TRACE_BEGIN();
      91           37 :     assert( classifier_id != DATA_ROW_VOID );
      92           37 :     assert( out_deleted_relationships != NULL );
      93           37 :     *out_deleted_relationships = 0;
      94           37 :     u8_error_t result = U8_ERROR_NONE;
      95              : 
      96              :     data_small_set_t relations_to_delete;
      97           37 :     data_small_set_init( &relations_to_delete );
      98              : 
      99              :     /* load relationships to be checked */
     100              :     data_relationship_iterator_t relationship_iterator;
     101           37 :     data_relationship_iterator_init_empty( &relationship_iterator );
     102           37 :     result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
     103              :                                                                        classifier_id,
     104              :                                                                        &relationship_iterator
     105              :                                                                      );
     106           37 :     if ( result == U8_ERROR_NONE )
     107              :     {
     108           67 :         while( data_relationship_iterator_has_next( &relationship_iterator ) )
     109              :         {
     110           31 :             result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship_buf) );
     111              : 
     112           31 :             bool visible = true;
     113              :             const u8_error_t vis_err
     114           31 :                 = consistency_relationship_private_is_shown_by_a_diagram( this_, &((*this_).temp_relationship_buf), &visible );
     115              : 
     116           31 :             if ( vis_err == U8_ERROR_NONE )
     117              :             {
     118           31 :                 if ( ! visible )
     119              :                 {
     120              :                     /* invisible relationship found */
     121              :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
     122            3 :                     const data_id_t relation_to_delete = data_relationship_get_data_id( &((*this_).temp_relationship_buf) );
     123            3 :                     result |= data_small_set_add_obj( &relations_to_delete, relation_to_delete );
     124              :                 }
     125              :             }
     126           31 :             result |= vis_err;
     127              :         }
     128              :     }
     129              :     else
     130              :     {
     131            1 :         U8_LOG_WARNING( "Relationships of the deleted classifier cannot be checked for being superfluous now." );
     132            1 :         U8_TRACE_INFO_INT( "classifier has unckecked relationships:", classifier_id );
     133              :     }
     134           37 :     result |= data_relationship_iterator_destroy( &relationship_iterator );
     135              :     /* note that relationship_iterator cannot be used here any longer due to re-entrancy by recursion */
     136              : 
     137              :     /* delete all found relationship */
     138           37 :     const uint32_t relations_count = data_small_set_get_count( &relations_to_delete );
     139           40 :     for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ )
     140              :     {
     141            3 :         const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 );
     142            3 :         assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP );
     143              :         const u8_error_t del_err
     144            3 :             = ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl,
     145              :                                                               data_id_get_row( &delete_rel ),
     146              :                                                               CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
     147              :                                                             );
     148            3 :         *out_deleted_relationships += ( del_err == U8_ERROR_NONE ) ? 1 : 0;
     149            3 :         result |= del_err;
     150              :     }
     151              : 
     152           37 :     data_small_set_destroy( &relations_to_delete );
     153              : 
     154           37 :     U8_TRACE_END_ERR( result );
     155           37 :     return result;
     156              : }
     157              : 
     158           31 : u8_error_t consistency_relationship_private_is_shown_by_a_diagram( consistency_relationship_t *this_,
     159              :                                                                    const data_relationship_t *relation,
     160              :                                                                    bool *out_result )
     161              : {
     162           31 :     U8_TRACE_BEGIN();
     163           31 :     assert( NULL != relation );
     164           31 :     assert( NULL != out_result );
     165           31 :     u8_error_t result = U8_ERROR_NONE;
     166              : 
     167           31 :     const data_row_t relationship_id = data_relationship_get_row( relation );
     168           31 :     bool a_diagram_shows_uncond_relationship = false;  /* tells if a diagram is found where unconditional relationships are visible */
     169           31 :     bool a_diagram_shows_scenario_relationship = false;  /* tells if a diagram is found where scenario relationships are visible */
     170              : 
     171              :     {
     172              :         data_diagram_iterator_t diagram_iterator;
     173           31 :         data_diagram_iterator_init_empty( &diagram_iterator );
     174              : 
     175           31 :         result |= data_database_reader_get_diagrams_by_relationship_id( (*this_).db_reader,
     176              :                                                                         relationship_id,
     177              :                                                                         &diagram_iterator
     178              :                                                                       );
     179              : 
     180           31 :         if ( result == U8_ERROR_NONE )
     181              :         {
     182           66 :             while ( data_diagram_iterator_has_next( &diagram_iterator ) )
     183              :             {
     184           35 :                 result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram_buf) );
     185           35 :                 const data_diagram_type_t diagram_type = data_diagram_get_diagram_type( &((*this_).temp_diagram_buf) );
     186           35 :                 a_diagram_shows_uncond_relationship |= data_rules_diagram_shows_uncond_relationships( &((*this_).rules), diagram_type );
     187              :                 /* Note that ..get_diagrams_by_relationship_id() returns scenario-based diagrams only if the relationship is visible there: */
     188           35 :                 a_diagram_shows_scenario_relationship |= data_rules_diagram_shows_scenario_relationships( &((*this_).rules), diagram_type );
     189              : 
     190              :                 /* Workaround: Box diagrams show containment relationships - this is not yet handled by (*this_).rules */
     191              :                 /* And possibly a problem because the use may change the type and bypass existing database triggers... TODO */
     192           35 :                 const bool keep_containment_at_box_diagram = ( data_relationship_get_main_type( relation ) == DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT )
     193           35 :                     && ( diagram_type == DATA_DIAGRAM_TYPE_BOX_DIAGRAM );
     194           35 :                 a_diagram_shows_uncond_relationship |= keep_containment_at_box_diagram;
     195              :             }
     196              :         }
     197              : 
     198           31 :         result |= data_diagram_iterator_destroy( &diagram_iterator );
     199              :     }
     200              : 
     201           31 :     *out_result = ( a_diagram_shows_uncond_relationship || a_diagram_shows_scenario_relationship );
     202              : 
     203           31 :     U8_TRACE_END_ERR( result );
     204           31 :     return result;
     205              : }
     206              : 
     207              : 
     208              : /*
     209              : Copyright 2018-2026 Andreas Warnke
     210              : 
     211              : Licensed under the Apache License, Version 2.0 (the "License");
     212              : you may not use this file except in compliance with the License.
     213              : You may obtain a copy of the License at
     214              : 
     215              :     http://www.apache.org/licenses/LICENSE-2.0
     216              : 
     217              : Unless required by applicable law or agreed to in writing, software
     218              : distributed under the License is distributed on an "AS IS" BASIS,
     219              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     220              : See the License for the specific language governing permissions and
     221              : limitations under the License.
     222              : */
        

Generated by: LCOV version 2.0-1