LCOV - code coverage report
Current view: top level - ctrl/source/consistency - consistency_lifeline.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 137 140 97.9 %
Date: 2024-12-21 18:34:41 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 "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-2024 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 1.16