LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_lifeline.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.5_covts Lines: 97.4 % 152 148
Test Date: 2026-05-28 21:31:40 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /* File: consistency_lifeline.c; Copyright and License: see below */
       2              : 
       3              : #include "consistency/consistency_lifeline.h"
       4              : #include "ctrl_classifier_controller.h"
       5              : #include "ctrl_diagram_controller.h"
       6              : #include "set/data_full_id_list.h"
       7              : #include "set/data_visible_set.h"
       8              : #include "u8/u8_trace.h"
       9              : #include "u8/u8_log.h"
      10              : 
      11              : /*!
      12              :  *  \brief constants of consistency_lifeline_t
      13              :  */
      14              : enum consistency_lifeline_const_enum {
      15              :     CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES = DATA_VISIBLE_SET_MAX_CLASSIFIERS,  /*!< maximum number of diagramelements in a diagram */
      16              : };
      17              : 
      18           47 : void consistency_lifeline_init( consistency_lifeline_t *this_,
      19              :                                 data_database_reader_t *db_reader,
      20              :                                 struct ctrl_classifier_controller_struct *clfy_ctrl,
      21              :                                 struct ctrl_diagram_controller_struct *diag_ctrl )
      22              : {
      23           47 :     U8_TRACE_BEGIN();
      24           47 :     assert( NULL != db_reader );
      25           47 :     assert( NULL != clfy_ctrl );
      26           47 :     assert( NULL != diag_ctrl );
      27              : 
      28           47 :     (*this_).db_reader = db_reader;
      29           47 :     (*this_).clfy_ctrl = clfy_ctrl;
      30           47 :     (*this_).diag_ctrl = diag_ctrl;
      31           47 :     data_rules_init( &((*this_).rules) );
      32              : 
      33           47 :     U8_TRACE_END();
      34           47 : }
      35              : 
      36           47 : void consistency_lifeline_destroy( consistency_lifeline_t *this_ )
      37              : {
      38           47 :     U8_TRACE_BEGIN();
      39              : 
      40           47 :     (*this_).db_reader = NULL;
      41           47 :     (*this_).clfy_ctrl = NULL;
      42           47 :     (*this_).diag_ctrl = NULL;
      43           47 :     data_rules_destroy( &((*this_).rules) );
      44              : 
      45           47 :     U8_TRACE_END();
      46           47 : }
      47              : 
      48            9 : u8_error_t consistency_lifeline_delete_lifelines ( consistency_lifeline_t *this_,
      49              :                                                    const data_diagram_t *updated_diagram,
      50              :                                                    consistency_stat_t *io_stat
      51              :                                                  )
      52              : {
      53            9 :     U8_TRACE_BEGIN();
      54            9 :     assert( NULL != updated_diagram );
      55            9 :     assert( NULL != io_stat );
      56            9 :     u8_error_t result = U8_ERROR_NONE;
      57              : 
      58            9 :     const data_diagram_type_t new_type = data_diagram_get_diagram_type ( updated_diagram );
      59            9 :     if ( ! data_rules_diagram_is_scenario( &((*this_).rules), new_type ) )
      60              :     {
      61              :         /* this diagram type must not have any lifelines */
      62              :         data_small_set_t lifelines_to_delete;
      63            5 :         data_small_set_init( &lifelines_to_delete );
      64              : 
      65              :         /* search all contained diagramelements */
      66            5 :         const data_row_t diagram_id = data_diagram_get_row ( updated_diagram );
      67              :         data_diagramelement_iterator_t diagramelement_iterator;
      68            5 :         data_diagramelement_iterator_init_empty( &diagramelement_iterator );
      69            5 :         result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
      70              :                                                                           diagram_id,
      71              :                                                                           &diagramelement_iterator
      72              :                                                                         );
      73            5 :         if ( U8_ERROR_NONE == result )
      74              :         {
      75              :             /* search the diagramelements */
      76           12 :             while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
      77              :             {
      78            7 :                 result |= data_diagramelement_iterator_next( &diagramelement_iterator, &((*this_).temp_diagelement_buf) );
      79              :                 const data_id_t feat_to_delete
      80            7 :                     = data_diagramelement_get_focused_feature_data_id( &((*this_).temp_diagelement_buf) );
      81            7 :                 if ( data_id_is_valid( &feat_to_delete ) )
      82              :                 {
      83              :                     /* diagramelement with a focused feature found */
      84              :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
      85            3 :                     result |= data_small_set_add_obj( &lifelines_to_delete, feat_to_delete );
      86              :                 }
      87              :             }
      88              :         }
      89              :         else
      90              :         {
      91            0 :             U8_LOG_ANOMALY( "consistency_lifeline_delete_lifelines could not load all diagram_elements of a diagram." );
      92              :         }
      93            5 :         result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
      94              : 
      95              :         /* delete all found lifelines */
      96              :         /* note that (*this_).temp_diagelement_buf cannot be used here any longer due to re-entrancy by recursion */
      97            5 :         const uint32_t lifelines_count = data_small_set_get_count( &lifelines_to_delete );
      98            8 :         for ( uint32_t index2 = 0; index2 < lifelines_count; index2 ++ )
      99              :         {
     100            3 :             const data_id_t delete_feat = data_small_set_get_id( &lifelines_to_delete, index2 );
     101            3 :             assert( data_id_get_table( &delete_feat ) == DATA_TABLE_FEATURE );
     102            3 :             result |= ctrl_classifier_controller_delete_feature( (*this_).clfy_ctrl,
     103              :                                                                  data_id_get_row( &delete_feat ),
     104              :                                                                  CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
     105              :                                                                  io_stat
     106              :                                                                );
     107              :             /* the current_diagele is already updated by another (recursive) consistency check. */
     108              :         }
     109              : 
     110            5 :         data_small_set_destroy( &lifelines_to_delete );
     111              :     }
     112              : 
     113            9 :     U8_TRACE_END_ERR( result );
     114            9 :     return result;
     115              : }
     116              : 
     117            9 : u8_error_t consistency_lifeline_create_lifelines( consistency_lifeline_t *this_,
     118              :                                                   const data_diagram_t *updated_diagram,
     119              :                                                   consistency_stat_t *io_stat )
     120              : {
     121            9 :     U8_TRACE_BEGIN();
     122            9 :     assert( NULL != updated_diagram );
     123            9 :     assert( NULL != io_stat );
     124            9 :     u8_error_t result = U8_ERROR_NONE;
     125              : 
     126            9 :     const data_diagram_type_t new_type = data_diagram_get_diagram_type ( updated_diagram );
     127            9 :     if ( data_rules_diagram_is_scenario( &((*this_).rules), new_type ) )
     128              :     {
     129              :         /* this diagram type needs lifelines */
     130              :         data_full_id_t lifelines_to_create_buf[ CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES ];
     131              :         data_full_id_list_t lifelines_to_create;
     132            4 :         data_full_id_list_init( &lifelines_to_create,
     133              :                                 CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES,
     134              :                                 &lifelines_to_create_buf
     135              :                               );
     136              : 
     137              :         /* search all contained diagramelements */
     138            4 :         const data_row_t diagram_id = data_diagram_get_row ( updated_diagram );
     139              :         data_diagramelement_iterator_t diagramelement_iterator;
     140            4 :         data_diagramelement_iterator_init_empty( &diagramelement_iterator );
     141            4 :         result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
     142              :                                                                           diagram_id,
     143              :                                                                           &diagramelement_iterator
     144              :                                                                         );
     145              : 
     146            4 :         if ( U8_ERROR_NONE == result )
     147              :         {
     148              :             /* search the diagramelements */
     149           13 :             while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
     150              :             {
     151            5 :                 result |= data_diagramelement_iterator_next( &diagramelement_iterator,
     152              :                                                              &((*this_).temp_diagelement_buf)
     153              :                                                            );
     154            5 :                 data_diagramelement_t *const current_diagele
     155              :                     = &((*this_).temp_diagelement_buf);
     156              :                 const data_row_t focused_feature
     157            5 :                     = data_diagramelement_get_focused_feature_row( current_diagele );
     158              : 
     159            5 :                 if ( DATA_ROW_VOID == focused_feature )
     160              :                 {
     161              :                     /* diagramelement without focused feature found */
     162              :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
     163              :                     const data_full_id_t diagramelement_ids = {
     164            4 :                         .primary_id = data_diagramelement_get_data_id( current_diagele ),
     165            4 :                         .secondary_id = data_diagramelement_get_classifier_data_id( current_diagele )
     166              :                     };
     167            4 :                     result |= data_full_id_list_add( &lifelines_to_create, &diagramelement_ids );
     168              :                 }
     169              :             }
     170              :         }
     171              :         else
     172              :         {
     173            0 :             U8_LOG_ANOMALY( "consistency_lifeline_create_lifelines could not load all diagram_elements of a diagram." );
     174              :         }
     175            4 :         result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
     176              : 
     177              : 
     178              :         /* create all missing lifelines */
     179              :         /* note that (*this_).private_temp_diagele_buf cannot be used here any longer due to re-entrancy by recursion */
     180            4 :         const uint32_t lifelines_count = data_full_id_list_get_length( &lifelines_to_create );
     181            8 :         for ( uint32_t index2 = 0; index2 < lifelines_count; index2 ++ )
     182              :         {
     183            4 :             const data_full_id_t *const diagramelement_ids = data_full_id_list_get_const( &lifelines_to_create, index2 );
     184            4 :             data_row_t lifeline_row = DATA_ROW_VOID;
     185              :             const u8_error_t create_err
     186            4 :                 = consistency_lifeline_private_create_one_lifeline ( this_, diagramelement_ids, &lifeline_row );
     187            4 :             if (( create_err == U8_ERROR_NONE )&&( lifeline_row != DATA_ROW_VOID ))
     188              :             {
     189            4 :                 consistency_stat_increment_lifelines( io_stat );
     190              :             }
     191            4 :             result |= create_err;
     192              :         }
     193              : 
     194            4 :         data_full_id_list_destroy( &lifelines_to_create );
     195              :     }
     196              : 
     197            9 :     U8_TRACE_END_ERR( result );
     198            9 :     return result;
     199              : }
     200              : 
     201           60 : u8_error_t consistency_lifeline_create_a_lifeline( consistency_lifeline_t *this_,
     202              :                                                    const data_diagramelement_t *new_diagramelement,
     203              :                                                    data_row_t *out_lifeline_row )
     204              : {
     205           60 :     U8_TRACE_BEGIN();
     206           60 :     assert( NULL != new_diagramelement );
     207           60 :     assert( NULL != out_lifeline_row );
     208           60 :     u8_error_t result = U8_ERROR_NONE;
     209              : 
     210              :     /* load the diagram and check the type */
     211              :     data_diagram_t the_diag;
     212           60 :     result |= data_database_reader_get_diagram_by_id( (*this_).db_reader,
     213              :                                                       data_diagramelement_get_diagram_row( new_diagramelement ),
     214              :                                                       &the_diag
     215              :                                                     );
     216              : 
     217           60 :     if ( U8_ERROR_NONE == result )
     218              :     {
     219           60 :         const data_diagram_type_t dig_type = data_diagram_get_diagram_type( &the_diag );
     220           60 :         if ( data_rules_diagram_is_scenario( &((*this_).rules), dig_type ) )
     221              :         {
     222              :             const data_full_id_t diagramelement_ids = {
     223           13 :                 .primary_id = data_diagramelement_get_data_id( new_diagramelement ),
     224           13 :                 .secondary_id = data_diagramelement_get_classifier_data_id( new_diagramelement )
     225              :             };
     226           13 :             result |= consistency_lifeline_private_create_one_lifeline ( this_, &diagramelement_ids, out_lifeline_row );
     227              :         }
     228              :         else
     229              :         {
     230              :             /* no lifeline in non-scenario diagrams */
     231           47 :             *out_lifeline_row = DATA_ROW_VOID;
     232              :         }
     233              :     }
     234              :     else
     235              :     {
     236              :         /* error: diagram type unknown */
     237            0 :         *out_lifeline_row = DATA_ROW_VOID;
     238              :     }
     239              : 
     240           60 :     U8_TRACE_END_ERR( result );
     241           60 :     return result;
     242              : }
     243              : 
     244           17 : u8_error_t consistency_lifeline_private_create_one_lifeline( consistency_lifeline_t *this_,
     245              :                                                              const data_full_id_t *diagramelement_ids,
     246              :                                                              data_row_t *out_lifeline_row )
     247              : {
     248           17 :     U8_TRACE_BEGIN();
     249           17 :     assert( NULL != diagramelement_ids );
     250           17 :     assert( NULL != out_lifeline_row );
     251           17 :     u8_error_t result = U8_ERROR_NONE;
     252           17 :     const data_id_t diagramelement_id = data_full_id_get_primary_id( diagramelement_ids );
     253           17 :     assert( DATA_TABLE_DIAGRAMELEMENT == data_id_get_table( &diagramelement_id ) );
     254           17 :     const data_id_t classifier_id = data_full_id_get_secondary_id( diagramelement_ids );
     255           17 :     assert( DATA_TABLE_CLASSIFIER == data_id_get_table( &classifier_id ) );
     256              : 
     257              :     /* define the lifeline to create */
     258              :     data_feature_t new_lifeline;
     259           17 :     result |= data_feature_init_new( &new_lifeline,
     260              :                                      DATA_FEATURE_TYPE_LIFELINE,
     261              :                                      data_id_get_row( &classifier_id ),
     262              :                                      "",  /* key */
     263              :                                      "",  /* value or type */
     264              :                                      "",  /* description */
     265              :                                      0  /* list_order */
     266              :                                    );
     267              : 
     268              :     /* create the lifeline */
     269           17 :     data_row_t new_feature_id = DATA_ROW_VOID;
     270           17 :     result |= ctrl_classifier_controller_create_feature( (*this_).clfy_ctrl,
     271              :                                                          &new_lifeline,
     272              :                                                          CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
     273              :                                                          &new_feature_id
     274              :                                                        );
     275              : 
     276              :     /* the newly created lifeline is the focused feature */
     277           17 :     result |= ctrl_diagram_controller_update_diagramelement_focused_feature_id( (*this_).diag_ctrl,
     278              :                                                                                 data_id_get_row( &diagramelement_id ),
     279              :                                                                                 new_feature_id,
     280              :                                                                                 CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
     281              :                                                                               );
     282              : 
     283              :     /* cleanup */
     284           17 :     data_feature_destroy ( &new_lifeline );
     285           17 :     *out_lifeline_row = new_feature_id;
     286              : 
     287           17 :     U8_TRACE_END_ERR( result );
     288           17 :     return result;
     289              : }
     290              : 
     291            9 : u8_error_t consistency_lifeline_delete_a_lifeline( consistency_lifeline_t *this_,
     292              :                                                    const data_diagramelement_t *deleted_diagramelement,
     293              :                                                    consistency_stat_t *io_stat )
     294              : {
     295            9 :     U8_TRACE_BEGIN();
     296            9 :     assert( NULL != deleted_diagramelement );
     297            9 :     assert( NULL != io_stat );
     298            9 :     u8_error_t result = U8_ERROR_NONE;
     299              : 
     300              :     /* delete the lifeline of the already deleted data_diagramelement_t */
     301              :     const data_row_t focused_feature_id
     302            9 :         = data_diagramelement_get_focused_feature_row( deleted_diagramelement );
     303            9 :     if ( DATA_ROW_VOID != focused_feature_id )
     304              :     {
     305            5 :         result |= ctrl_classifier_controller_delete_feature( (*this_).clfy_ctrl,
     306              :                                                              focused_feature_id,
     307              :                                                              CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
     308              :                                                              io_stat
     309              :                                                            );
     310              :     }
     311              : 
     312            9 :     U8_TRACE_END_ERR( result );
     313            9 :     return result;
     314              : }
     315              : 
     316            9 : u8_error_t consistency_lifeline_unlink_lifeline( consistency_lifeline_t *this_,
     317              :                                                  const data_feature_t *deleted_feature )
     318              : {
     319            9 :     U8_TRACE_BEGIN();
     320            9 :     assert( NULL != deleted_feature );
     321            9 :     u8_error_t result = U8_ERROR_NONE;
     322              : 
     323            9 :     if ( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type ( deleted_feature ) )
     324              :     {
     325            9 :         const data_row_t classifier_id = data_feature_get_classifier_row ( deleted_feature );
     326            9 :         const data_row_t deleted_feature_id = data_feature_get_row( deleted_feature );
     327              :         data_small_set_t diag_ele_to_unlink;
     328            9 :         data_small_set_init( &diag_ele_to_unlink );
     329              : 
     330              :         /* search all diagramelements of the classifier */
     331              :         data_diagramelement_iterator_t diagramelement_iterator;
     332            9 :         data_diagramelement_iterator_init_empty( &diagramelement_iterator );
     333            9 :         result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
     334              :                                                                              classifier_id,
     335              :                                                                              &diagramelement_iterator
     336              :                                                                            );
     337              : 
     338            9 :         if ( U8_ERROR_NONE == result )
     339              :         {
     340              :             /* search the diagramelements */
     341           30 :             while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
     342              :             {
     343           12 :                 result |= data_diagramelement_iterator_next( &diagramelement_iterator, &((*this_).temp_diagelement_buf) );
     344           12 :                 data_diagramelement_t *const current_diagele
     345              :                     = &((*this_).temp_diagelement_buf);
     346              :                 const data_row_t focused_feature
     347           12 :                     = data_diagramelement_get_focused_feature_row( current_diagele );
     348              : 
     349           12 :                 if ( focused_feature == deleted_feature_id )
     350              :                 {
     351              :                     /* diagramelement with the just deleted focused feature found */
     352              :                     /* this must be copied into a local data set to make this class re-entrant for recursive calls */
     353            4 :                     const data_id_t diagele_id = data_diagramelement_get_data_id( current_diagele );
     354            4 :                     result |= data_small_set_add_obj( &diag_ele_to_unlink, diagele_id );
     355              :                 }
     356              :             }
     357              :         }
     358              :         else
     359              :         {
     360            0 :             U8_LOG_ANOMALY( "consistency_lifeline_unlink_lifeline could not load all lifelines of a classifier." );
     361              :         }
     362            9 :         result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
     363              : 
     364              :         /* unlink all found diagram elements (there should be exactly one) */
     365              :         /* note that (*this_).private_temp_diagele_buf cannot be used here any longer due to re-entrancy by recursion */
     366            9 :         const uint32_t diag_ele_count = data_small_set_get_count( &diag_ele_to_unlink );
     367            9 :         if ( diag_ele_count != 1 )
     368              :         {
     369            5 :             U8_LOG_ANOMALY_INT( "Unlinking a just deleted lifeline that had not exactly one occurrence:",
     370              :                                 diag_ele_count
     371              :                               );
     372              :         }
     373           13 :         for ( uint32_t index2 = 0; index2 < diag_ele_count; index2 ++ )
     374              :         {
     375            4 :             const data_id_t diagele_to_unlink = data_small_set_get_id( &diag_ele_to_unlink, index2 );
     376            4 :             assert( data_id_get_table( &diagele_to_unlink ) == DATA_TABLE_DIAGRAMELEMENT );
     377            4 :             result |= ctrl_diagram_controller_update_diagramelement_focused_feature_id( (*this_).diag_ctrl,
     378              :                                                                                         data_id_get_row( &diagele_to_unlink ),
     379              :                                                                                         DATA_ROW_VOID,
     380              :                                                                                         CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
     381              :                                                                                       );
     382              :         }
     383              : 
     384            9 :         data_small_set_destroy( &diag_ele_to_unlink );
     385              :     }
     386              : 
     387            9 :     U8_TRACE_END_ERR( result );
     388            9 :     return result;
     389              : }
     390              : 
     391              : 
     392              : /*
     393              : Copyright 2018-2026 Andreas Warnke
     394              : 
     395              : Licensed under the Apache License, Version 2.0 (the "License");
     396              : you may not use this file except in compliance with the License.
     397              : You may obtain a copy of the License at
     398              : 
     399              :     http://www.apache.org/licenses/LICENSE-2.0
     400              : 
     401              : Unless required by applicable law or agreed to in writing, software
     402              : distributed under the License is distributed on an "AS IS" BASIS,
     403              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     404              : See the License for the specific language governing permissions and
     405              : limitations under the License.
     406              : */
        

Generated by: LCOV version 2.0-1