LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_lifeline.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.58.2_covts Lines: 134 137 97.8 %
Date: 2024-05-12 08:28:01 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.16