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

Generated by: LCOV version 2.0-1