LCOV - code coverage report
Current view: top level - ctrl/source - ctrl_multi_step_changer.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 214 267 80.1 %
Date: 2024-04-07 11:14:42 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /* File: ctrl_multi_step_changer.c; Copyright and License: see below */
       2             : 
       3             : #include "ctrl_multi_step_changer.h"
       4             : #include "u8/u8_trace.h"
       5             : #include "u8/u8_log.h"
       6             : #include <assert.h>
       7             : 
       8          21 : void ctrl_multi_step_changer_init ( ctrl_multi_step_changer_t *this_,
       9             :                                     ctrl_controller_t *controller,
      10             :                                     data_database_reader_t *db_reader )
      11             : {
      12          21 :     U8_TRACE_BEGIN();
      13          21 :     assert( NULL != controller );
      14          21 :     assert( NULL != db_reader );
      15             : 
      16             :     /* init member attributes */
      17          21 :     (*this_).controller = controller;
      18          21 :     (*this_).db_reader = db_reader;
      19             : 
      20          21 :     (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_START_NEW;
      21             : 
      22          21 :     U8_TRACE_END();
      23          21 : }
      24             : 
      25          21 : void ctrl_multi_step_changer_destroy ( ctrl_multi_step_changer_t *this_ )
      26             : {
      27          21 :     U8_TRACE_BEGIN();
      28          21 :     assert( NULL != (*this_).controller );
      29          21 :     assert( NULL != (*this_).db_reader );
      30             : 
      31             :     /* destroy member attributes */
      32          21 :     (*this_).controller = NULL;
      33          21 :     (*this_).db_reader = NULL;
      34             : 
      35          21 :     U8_TRACE_END();
      36          21 : }
      37             : 
      38             : /* ================================ delete sets of elements ================================ */
      39             : 
      40           3 : u8_error_t ctrl_multi_step_changer_delete_set ( ctrl_multi_step_changer_t *this_,
      41             :                                                 const data_small_set_t *objects,
      42             :                                                 data_stat_t *io_stat )
      43             : {
      44           3 :     U8_TRACE_BEGIN();
      45           3 :     assert ( NULL != io_stat );
      46           3 :     u8_error_t result = U8_ERROR_NONE;
      47             : 
      48           3 :     if ( data_small_set_is_empty( objects ) )
      49             :     {
      50           0 :         result = U8_ERROR_INPUT_EMPTY;
      51             :     }
      52             :     else
      53             :     {
      54             :         int index;
      55             : 
      56           3 :         ctrl_classifier_controller_t *const classifier_ctrl = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
      57           3 :         ctrl_diagram_controller_t *const diagram_ctrl = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
      58             : 
      59             :         /* STEP ZERO: Delete all objects that can be immediately deleted */
      60             : 
      61          15 :         for ( index = 0; index < data_small_set_get_count( objects ); index ++ )
      62             :         {
      63             :             data_id_t current_id;
      64          12 :             current_id = data_small_set_get_id( objects, index );
      65          12 :             switch ( data_id_get_table( &current_id ) )
      66             :             {
      67           2 :                 case DATA_TABLE_CLASSIFIER:
      68             :                 {
      69             :                     /* see step two */
      70             :                 }
      71           2 :                 break;
      72             : 
      73           3 :                 case DATA_TABLE_FEATURE:
      74             :                 {
      75           3 :                     result |= ctrl_classifier_controller_delete_feature ( classifier_ctrl,
      76             :                                                                           data_id_get_row_id( &current_id ),
      77             :                                                                           (*this_).is_first_step
      78             :                                                                         );
      79           3 :                     if ( result == U8_ERROR_NONE )
      80             :                     {
      81           2 :                         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
      82             :                     }
      83             :                     else
      84             :                     {
      85           1 :                         data_stat_inc_count( io_stat, DATA_STAT_TABLE_FEATURE, DATA_STAT_SERIES_ERROR );
      86             :                     }
      87             :                 }
      88           3 :                 break;
      89             : 
      90           3 :                 case DATA_TABLE_RELATIONSHIP:
      91             :                 {
      92           3 :                     result |= ctrl_classifier_controller_delete_relationship ( classifier_ctrl,
      93             :                                                                                data_id_get_row_id( &current_id ),
      94             :                                                                                (*this_).is_first_step
      95             :                                                                              );
      96           3 :                     if ( result == U8_ERROR_NONE )
      97             :                     {
      98           2 :                         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
      99             :                     }
     100             :                     else
     101             :                     {
     102           1 :                         data_stat_inc_count( io_stat, DATA_STAT_TABLE_RELATIONSHIP, DATA_STAT_SERIES_ERROR );
     103             :                     }
     104             :                 }
     105           3 :                 break;
     106             : 
     107           2 :                 case DATA_TABLE_DIAGRAMELEMENT:
     108             :                 {
     109             :                     /* see step one */
     110             :                 }
     111           2 :                 break;
     112             : 
     113           2 :                 case DATA_TABLE_DIAGRAM:
     114             :                 {
     115             :                     /* see step two */
     116             :                 }
     117           2 :                 break;
     118             : 
     119           0 :                 default:
     120             :                 {
     121           0 :                     result |= U8_ERROR_VALUE_OUT_OF_RANGE;
     122             :                 }
     123           0 :                 break;
     124             :             }
     125             :         }
     126             : 
     127             :         /* STEP ONE: Delete all objects that can be deleted after relationships and features are gone */
     128             : 
     129          15 :         for ( index = 0; index < data_small_set_get_count( objects ); index ++ )
     130             :         {
     131             :             data_id_t current_id;
     132          12 :             current_id = data_small_set_get_id( objects, index );
     133          12 :             switch ( data_id_get_table( &current_id ) )
     134             :             {
     135           2 :                 case DATA_TABLE_CLASSIFIER:
     136             :                 {
     137             :                     /* see step two */
     138             :                 }
     139           2 :                 break;
     140             : 
     141           3 :                 case DATA_TABLE_FEATURE:
     142             :                 {
     143             :                     /* see step zero */
     144             :                 }
     145           3 :                 break;
     146             : 
     147           3 :                 case DATA_TABLE_RELATIONSHIP:
     148             :                 {
     149             :                     /* see step zero */
     150             :                 }
     151           3 :                 break;
     152             : 
     153           2 :                 case DATA_TABLE_DIAGRAMELEMENT:
     154             :                 {
     155           2 :                     result |= ctrl_diagram_controller_delete_diagramelement ( diagram_ctrl,
     156             :                                                                               data_id_get_row_id( &current_id ),
     157             :                                                                               (*this_).is_first_step
     158             :                                                                             );
     159           2 :                     if ( result == U8_ERROR_NONE )
     160             :                     {
     161           1 :                         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     162             :                     }
     163             :                     else
     164             :                     {
     165           1 :                         data_stat_inc_count( io_stat, DATA_STAT_TABLE_DIAGRAMELEMENT, DATA_STAT_SERIES_ERROR );
     166             :                     }
     167             :                 }
     168           2 :                 break;
     169             : 
     170           2 :                 case DATA_TABLE_DIAGRAM:
     171             :                 {
     172             :                     /* see step two */
     173             :                 }
     174           2 :                 break;
     175             : 
     176           0 :                 default:
     177             :                 {
     178             :                     /* see step zero */
     179             :                 }
     180           0 :                 break;
     181             :             }
     182             :         }
     183             : 
     184             :         /* STEP TWO: Delete all objects that can be deleted after step one */
     185             : 
     186          15 :         for ( index = 0; index < data_small_set_get_count( objects ); index ++ )
     187             :         {
     188             :             data_id_t current_id;
     189          12 :             current_id = data_small_set_get_id( objects, index );
     190          12 :             switch ( data_id_get_table( &current_id ) )
     191             :             {
     192           2 :                 case DATA_TABLE_CLASSIFIER:
     193             :                 {
     194           2 :                     result |= ctrl_classifier_controller_delete_classifier( classifier_ctrl,
     195             :                                                                             data_id_get_row_id( &current_id ),
     196             :                                                                             (*this_).is_first_step
     197             :                                                                           );
     198           2 :                     if ( result == U8_ERROR_NONE )
     199             :                     {
     200           1 :                         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     201             :                     }
     202             :                     else
     203             :                     {
     204           1 :                         data_stat_inc_count( io_stat, DATA_STAT_TABLE_CLASSIFIER, DATA_STAT_SERIES_ERROR );
     205             :                     }
     206             :                 }
     207           2 :                 break;
     208             : 
     209           3 :                 case DATA_TABLE_FEATURE:
     210             :                 {
     211             :                     /* see step zero */
     212             :                 }
     213           3 :                 break;
     214             : 
     215           3 :                 case DATA_TABLE_RELATIONSHIP:
     216             :                 {
     217             :                     /* see step zero */
     218             :                 }
     219           3 :                 break;
     220             : 
     221           2 :                 case DATA_TABLE_DIAGRAMELEMENT:
     222             :                 {
     223             :                     /* see step one */
     224             :                 }
     225           2 :                 break;
     226             : 
     227           2 :                 case DATA_TABLE_DIAGRAM:
     228             :                 {
     229           2 :                     result |= ctrl_diagram_controller_delete_diagram ( diagram_ctrl,
     230             :                                                                        data_id_get_row_id( &current_id ),
     231             :                                                                        (*this_).is_first_step
     232             :                                                                      );
     233           2 :                     if ( result == U8_ERROR_NONE )
     234             :                     {
     235           1 :                         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     236             :                     }
     237             :                     else
     238             :                     {
     239           1 :                         data_stat_inc_count( io_stat, DATA_STAT_TABLE_DIAGRAM, DATA_STAT_SERIES_ERROR );
     240             :                     }
     241             :                 }
     242           2 :                 break;
     243             : 
     244           0 :                 default:
     245             :                 {
     246             :                     /* see step zero */
     247             :                 }
     248           0 :                 break;
     249             :             }
     250             :         }
     251             : 
     252             :         /* update statistics based on undo redo list */
     253           3 :         result |= ctrl_controller_get_statistics( (*this_).controller, io_stat );
     254             :     }
     255             : 
     256           3 :     U8_TRACE_END_ERR( result );
     257           3 :     return result;
     258             : }
     259             : 
     260             : /* ================================ create elements without duplicate ids ================================ */
     261             : 
     262           6 : u8_error_t ctrl_multi_step_changer_create_diagram ( ctrl_multi_step_changer_t *this_,
     263             :                                                     data_diagram_t *new_diagram,
     264             :                                                     u8_error_t* out_info )
     265             : {
     266           6 :     U8_TRACE_BEGIN();
     267           6 :     assert( NULL != new_diagram );
     268           6 :     assert( NULL != out_info );
     269           6 :     u8_error_t result = U8_ERROR_NONE;
     270             : 
     271             :     /* ensure that a uuid exists */
     272           6 :     if ( 0 == utf8string_get_length( data_diagram_get_uuid_const( new_diagram ) ) )
     273             :     {
     274             :         data_uuid_t new_uuid;
     275           0 :         data_uuid_init_new( &new_uuid );
     276           0 :         data_diagram_set_uuid( new_diagram, data_uuid_get_string( &new_uuid ) );
     277           0 :         data_uuid_destroy( &new_uuid );
     278             :     }
     279             : 
     280             :     ctrl_diagram_controller_t *const diagram_ctrl
     281           6 :         = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
     282             : 
     283             :     data_row_id_t new_diagram_id;
     284             :     const u8_error_t create_err
     285           6 :         = ctrl_diagram_controller_create_diagram( diagram_ctrl,
     286             :                                                   new_diagram,
     287             :                                                   (*this_).is_first_step,
     288             :                                                   &new_diagram_id
     289             :                                                 );
     290           6 :     *out_info = create_err;
     291           6 :     if ( create_err == U8_ERROR_NONE )
     292             :     {
     293           5 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     294           5 :         data_diagram_set_row_id( new_diagram, new_diagram_id );
     295             :     }
     296           1 :     else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
     297             :     {
     298           1 :         data_diagram_set_row_id( new_diagram, DATA_ROW_ID_VOID );
     299             :         const u8_error_t alt_create_err
     300           1 :             = ctrl_diagram_controller_create_diagram( diagram_ctrl,
     301             :                                                       new_diagram,
     302             :                                                       (*this_).is_first_step,
     303             :                                                       &new_diagram_id
     304             :                                                     );
     305           1 :         if ( alt_create_err == U8_ERROR_NONE )
     306             :         {
     307           1 :             (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     308           1 :             data_diagram_set_row_id( new_diagram, new_diagram_id );
     309           1 :             *out_info |= U8_ERROR_DUPLICATE_ID;
     310             :         }
     311             :         else
     312             :         {
     313           0 :             result = alt_create_err;
     314             :         }
     315             :     }
     316             :     else
     317             :     {
     318           0 :         result = create_err;
     319             :     }
     320             : 
     321           6 :     U8_TRACE_END_ERR( result );
     322           6 :     return result;
     323             : }
     324             : 
     325          16 : u8_error_t ctrl_multi_step_changer_create_diagramelement ( ctrl_multi_step_changer_t *this_,
     326             :                                                            data_diagramelement_t *new_diagramelement,
     327             :                                                            u8_error_t* out_info )
     328             : {
     329          16 :     U8_TRACE_BEGIN();
     330          16 :     assert( NULL != new_diagramelement );
     331          16 :     assert( NULL != out_info );
     332          16 :     u8_error_t result = U8_ERROR_NONE;
     333             : 
     334             :     /* ensure that a uuid exists */
     335          16 :     if ( 0 == utf8string_get_length( data_diagramelement_get_uuid_const( new_diagramelement ) ) )
     336             :     {
     337             :         data_uuid_t new_uuid;
     338           0 :         data_uuid_init_new( &new_uuid );
     339           0 :         data_diagramelement_set_uuid( new_diagramelement, data_uuid_get_string( &new_uuid ) );
     340           0 :         data_uuid_destroy( &new_uuid );
     341             :     }
     342             : 
     343             :     ctrl_diagram_controller_t *const diagram_ctrl
     344          16 :         = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
     345             : 
     346             :     data_row_id_t new_diagramelement_id;
     347             :     const u8_error_t create_err
     348          16 :         = ctrl_diagram_controller_create_diagramelement( diagram_ctrl,
     349             :                                                          new_diagramelement,
     350             :                                                          (*this_).is_first_step,
     351             :                                                          &new_diagramelement_id
     352             :                                                        );
     353          16 :     *out_info = create_err;
     354          16 :     if ( create_err == U8_ERROR_NONE )
     355             :     {
     356          16 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     357          16 :         data_diagramelement_set_row_id( new_diagramelement, new_diagramelement_id );
     358             :     }
     359           0 :     else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
     360             :     {
     361           0 :         data_diagramelement_set_row_id( new_diagramelement, DATA_ROW_ID_VOID );
     362             :         const u8_error_t alt_create_err
     363           0 :             = ctrl_diagram_controller_create_diagramelement( diagram_ctrl,
     364             :                                                              new_diagramelement,
     365             :                                                              (*this_).is_first_step,
     366             :                                                              &new_diagramelement_id
     367             :                                                            );
     368           0 :         if ( alt_create_err == U8_ERROR_NONE )
     369             :         {
     370           0 :             (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     371           0 :             data_diagramelement_set_row_id( new_diagramelement, new_diagramelement_id );
     372           0 :             *out_info |= U8_ERROR_DUPLICATE_ID;
     373             :         }
     374             :         else
     375             :         {
     376           0 :             result = alt_create_err;
     377             :         }
     378             :     }
     379             :     else
     380             :     {
     381           0 :         result = create_err;
     382             :     }
     383             : 
     384          16 :     U8_TRACE_END_ERR( result );
     385          16 :     return result;
     386             : }
     387             : 
     388          13 : u8_error_t ctrl_multi_step_changer_create_classifier ( ctrl_multi_step_changer_t *this_,
     389             :                                                        data_classifier_t *new_classifier,
     390             :                                                        u8_error_t* out_info )
     391             : {
     392          13 :     U8_TRACE_BEGIN();
     393          13 :     assert( NULL != new_classifier );
     394          13 :     assert( NULL != out_info );
     395          13 :     u8_error_t result = U8_ERROR_NONE;
     396             : 
     397             :     /* ensure that a uuid exists */
     398          13 :     if ( 0 == utf8string_get_length( data_classifier_get_uuid_const( new_classifier ) ) )
     399             :     {
     400             :         data_uuid_t new_uuid;
     401           0 :         data_uuid_init_new( &new_uuid );
     402           0 :         data_classifier_set_uuid( new_classifier, data_uuid_get_string( &new_uuid ) );
     403           0 :         data_uuid_destroy( &new_uuid );
     404             :     }
     405             : 
     406             :     ctrl_classifier_controller_t *const classifier_ctrl
     407          13 :         = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
     408             : 
     409             :     data_row_id_t new_classifier_id;
     410             :     const u8_error_t create_err
     411          13 :         = ctrl_classifier_controller_create_classifier( classifier_ctrl,
     412             :                                                         new_classifier,
     413             :                                                         (*this_).is_first_step,
     414             :                                                         &new_classifier_id
     415             :                                                       );
     416          13 :     *out_info = create_err;
     417          13 :     if ( create_err == U8_ERROR_NONE )
     418             :     {
     419          10 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     420          10 :         data_classifier_set_row_id( new_classifier, new_classifier_id );
     421             :     }
     422           3 :     else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
     423             :     {
     424           3 :         data_classifier_set_row_id( new_classifier, DATA_ROW_ID_VOID );
     425             :         const u8_error_t alt_create_err
     426           3 :             = ctrl_classifier_controller_create_classifier( classifier_ctrl,
     427             :                                                             new_classifier,
     428             :                                                             (*this_).is_first_step,
     429             :                                                             &new_classifier_id
     430             :                                                           );
     431           3 :         if ( alt_create_err == U8_ERROR_NONE )
     432             :         {
     433           0 :             (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     434           0 :             data_classifier_set_row_id( new_classifier, new_classifier_id );
     435           0 :             *out_info |= U8_ERROR_DUPLICATE_ID;
     436             :         }
     437             :         else
     438             :         {
     439           3 :             result = alt_create_err;
     440             :         }
     441             :     }
     442             :     else
     443             :     {
     444           0 :         result = create_err;
     445             :     }
     446             : 
     447          13 :     if ( u8_error_contains( result, U8_ERROR_DUPLICATE ) )
     448             :     {
     449           3 :         *out_info |= result;
     450           3 :         result = U8_ERROR_NONE;
     451             : 
     452             :         /* find an alternative, unused name */
     453             :         char wish_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
     454           3 :         utf8stringbuf_t wish_name = UTF8STRINGBUF( wish_name_buf );
     455           3 :         result |= utf8stringbuf_copy_str( wish_name, data_classifier_get_name_const( new_classifier ) );  /* error to be reported to caller */
     456             :         {
     457           3 :             bool name_ok = false;
     458             :             static const uint_fast16_t MAX_SEARCH_STEP = 10000;
     459             :             static const uint_fast16_t FIRST_STEP = 2;
     460           7 :             for ( uint_fast16_t search_step = FIRST_STEP; ( search_step < MAX_SEARCH_STEP )&&( ! name_ok )&&( result == U8_ERROR_NONE ); search_step ++ )
     461             :             {
     462             :                 char new_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
     463           4 :                 utf8stringbuf_t new_name = UTF8STRINGBUF( new_name_buf );
     464             :                 const u8_error_t trunc_err
     465           4 :                     = ctrl_multi_step_changer_private_propose_classifier_name( this_,
     466           4 :                                                                                utf8stringbuf_get_string( wish_name ),
     467             :                                                                                search_step,
     468             :                                                                                new_name
     469             :                                                                              );
     470           4 :                 if ( trunc_err != U8_ERROR_NONE )
     471             :                 {
     472           0 :                     U8_TRACE_INFO_STR("Name truncated at search for alternative:", utf8stringbuf_get_string( new_name ) );
     473             :                 }
     474           4 :                 data_classifier_set_name( new_classifier, utf8stringbuf_get_string( new_name ) );
     475             :                 const u8_error_t retry_err
     476           4 :                     = ctrl_classifier_controller_create_classifier( classifier_ctrl,
     477             :                                                                     new_classifier,
     478             :                                                                     (*this_).is_first_step,
     479             :                                                                     &new_classifier_id
     480             :                                                                   );
     481           4 :                 if ( u8_error_contains( retry_err, U8_ERROR_DUPLICATE ) )
     482             :                 {
     483           1 :                     *out_info |= retry_err;
     484             :                 }
     485           3 :                 else if ( retry_err == U8_ERROR_NONE )
     486             :                 {
     487           3 :                     name_ok = true;  /* name unused */
     488           3 :                     (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     489           3 :                     data_classifier_set_row_id( new_classifier, new_classifier_id );
     490           3 :                     *out_info |= U8_ERROR_DUPLICATE_NAME;
     491             :                 }
     492             :                 else
     493             :                 {
     494           0 :                     result |= retry_err;
     495             :                 }
     496             :             }
     497             :         }
     498             :     }
     499             : 
     500          13 :     U8_TRACE_END_ERR( result );
     501          13 :     return result;
     502             : }
     503             : 
     504           9 : u8_error_t ctrl_multi_step_changer_create_feature ( ctrl_multi_step_changer_t *this_,
     505             :                                                     data_feature_t *new_feature,
     506             :                                                     u8_error_t* out_info )
     507             : {
     508           9 :     U8_TRACE_BEGIN();
     509           9 :     assert( NULL != new_feature );
     510           9 :     assert( NULL != out_info );
     511           9 :     u8_error_t result = U8_ERROR_NONE;
     512             : 
     513             :     /* ensure that a uuid exists */
     514           9 :     if ( 0 == utf8string_get_length( data_feature_get_uuid_const( new_feature ) ) )
     515             :     {
     516             :         data_uuid_t new_uuid;
     517           0 :         data_uuid_init_new( &new_uuid );
     518           0 :         data_feature_set_uuid( new_feature, data_uuid_get_string( &new_uuid ) );
     519           0 :         data_uuid_destroy( &new_uuid );
     520             :     }
     521             : 
     522             :     ctrl_classifier_controller_t *const classifier_ctrl
     523           9 :         = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
     524             : 
     525             :     data_row_id_t new_feature_id;
     526             :     const u8_error_t create_err
     527           9 :         = ctrl_classifier_controller_create_feature( classifier_ctrl,
     528             :                                                      new_feature,
     529             :                                                      (*this_).is_first_step,
     530             :                                                      &new_feature_id
     531             :                                                    );
     532           9 :     *out_info = create_err;
     533           9 :     if ( create_err == U8_ERROR_NONE )
     534             :     {
     535           8 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     536           8 :         data_feature_set_row_id( new_feature, new_feature_id );
     537             :     }
     538           1 :     else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE) )
     539             :     {
     540           1 :         data_feature_set_row_id( new_feature, DATA_ROW_ID_VOID );
     541             :         const u8_error_t alt_create_err
     542           1 :             = ctrl_classifier_controller_create_feature( classifier_ctrl,
     543             :                                                          new_feature,
     544             :                                                          (*this_).is_first_step,
     545             :                                                          &new_feature_id
     546             :                                                        );
     547           1 :         if ( alt_create_err == U8_ERROR_NONE )
     548             :         {
     549           1 :             (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     550           1 :             data_feature_set_row_id( new_feature, new_feature_id );
     551           1 :             *out_info |= U8_ERROR_DUPLICATE_ID;
     552             :         }
     553             :         else
     554             :         {
     555           0 :             result = alt_create_err;
     556             :         }
     557             :     }
     558             :     else
     559             :     {
     560           0 :         result = create_err;
     561             :     }
     562             : 
     563           9 :     U8_TRACE_END_ERR( result );
     564           9 :     return result;
     565             : }
     566             : 
     567           7 : u8_error_t ctrl_multi_step_changer_create_relationship ( ctrl_multi_step_changer_t *this_,
     568             :                                                          data_relationship_t *new_relationship,
     569             :                                                          u8_error_t* out_info )
     570             : {
     571           7 :     U8_TRACE_BEGIN();
     572           7 :     assert( NULL != new_relationship );
     573           7 :     assert( NULL != out_info );
     574           7 :     u8_error_t result = U8_ERROR_NONE;
     575             : 
     576             :     /* ensure that a uuid exists */
     577           7 :     if ( 0 == utf8string_get_length( data_relationship_get_uuid_const( new_relationship ) ) )
     578             :     {
     579             :         data_uuid_t new_uuid;
     580           0 :         data_uuid_init_new( &new_uuid );
     581           0 :         data_relationship_set_uuid( new_relationship, data_uuid_get_string( &new_uuid ) );
     582           0 :         data_uuid_destroy( &new_uuid );
     583             :     }
     584             : 
     585             :     ctrl_classifier_controller_t *const classifier_ctrl
     586           7 :         = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
     587             : 
     588             :     data_row_id_t new_relationship_id;
     589             :     const u8_error_t create_err
     590           7 :         = ctrl_classifier_controller_create_relationship( classifier_ctrl,
     591             :                                                           new_relationship,
     592             :                                                           (*this_).is_first_step,
     593             :                                                           &new_relationship_id
     594             :                                                         );
     595           7 :     *out_info = create_err;
     596           7 :     if ( create_err == U8_ERROR_NONE )
     597             :     {
     598           5 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     599           5 :         data_relationship_set_row_id( new_relationship, new_relationship_id );
     600             :     }
     601           2 :     else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE) )
     602             :     {
     603           2 :         data_relationship_set_row_id( new_relationship, DATA_ROW_ID_VOID );
     604             :         const u8_error_t alt_create_err
     605           2 :             = ctrl_classifier_controller_create_relationship( classifier_ctrl,
     606             :                                                               new_relationship,
     607             :                                                               (*this_).is_first_step,
     608             :                                                               &new_relationship_id
     609             :                                                             );
     610           2 :         if ( alt_create_err == U8_ERROR_NONE )
     611             :         {
     612           2 :             (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     613           2 :             data_relationship_set_row_id( new_relationship, new_relationship_id );
     614           2 :             *out_info |= U8_ERROR_DUPLICATE_ID;
     615             :         }
     616             :         else
     617             :         {
     618           0 :             result = alt_create_err;
     619             :         }
     620             :     }
     621             :     else
     622             :     {
     623           0 :         result = create_err;
     624             :     }
     625             : 
     626           7 :     U8_TRACE_END_ERR( result );
     627           7 :     return result;
     628             : }
     629             : 
     630             : /* ================================ update links of existing elements  ================================ */
     631             : 
     632           0 : u8_error_t ctrl_multi_step_changer_update_diagram_parent_id ( ctrl_multi_step_changer_t *this_,
     633             :                                                               data_row_id_t diagram_id,
     634             :                                                               data_row_id_t new_diagram_parent_id )
     635             : {
     636           0 :     U8_TRACE_BEGIN();
     637           0 :     u8_error_t result = U8_ERROR_NONE;
     638             : 
     639             :     ctrl_diagram_controller_t *const diagram_ctrl
     640           0 :         = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
     641             : 
     642           0 :     result = ctrl_diagram_controller_update_diagram_parent_id( diagram_ctrl,
     643             :                                                                diagram_id,
     644             :                                                                new_diagram_parent_id,
     645             :                                                                (*this_).is_first_step
     646             :                                                              );
     647           0 :     if ( result == U8_ERROR_NONE )
     648             :     {
     649           0 :         (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
     650             :     }
     651             : 
     652           0 :     U8_TRACE_END_ERR( result );
     653           0 :     return result;
     654             : }
     655             : 
     656             : /* ================================ propose names of classifiers ================================ */
     657             : 
     658           4 : u8_error_t ctrl_multi_step_changer_private_propose_classifier_name ( ctrl_multi_step_changer_t *this_,
     659             :                                                                      const char* base_classifier_name,
     660             :                                                                      uint_fast16_t iteration,
     661             :                                                                      utf8stringbuf_t out_name )
     662             : {
     663           4 :     U8_TRACE_BEGIN();
     664           4 :     const size_t RESERVED_FOR_NUMBER = 5;
     665           4 :     assert( NULL != base_classifier_name );
     666           4 :     assert( utf8stringbuf_get_size(out_name) > RESERVED_FOR_NUMBER );
     667           4 :     u8_error_t result = U8_ERROR_NONE;
     668             : 
     669             :     /* find an alternative, unused name */
     670             :     /* copy the base_classifier_name to newname_buf */
     671             :     {
     672             :         utf8stringbuf_t shortened_new_name
     673           4 :             = utf8stringbuf_init( utf8stringbuf_get_size(out_name)-RESERVED_FOR_NUMBER, utf8stringbuf_get_string(out_name) );
     674           4 :         result |= utf8stringbuf_copy_str( shortened_new_name, base_classifier_name );
     675             :         /* null termination is guaranteed, also this function does not cut an utf8 code point in the middle. */
     676             :     }
     677             :     /* append a separator and the iteration number */
     678           4 :     result |= utf8stringbuf_append_str( out_name, "-" );
     679           4 :     result |= utf8stringbuf_append_int( out_name, iteration );
     680             : 
     681           4 :     U8_TRACE_END_ERR( result );
     682           4 :     return result;
     683             : }
     684             : 
     685             : 
     686             : /*
     687             : Copyright 2016-2024 Andreas Warnke
     688             : 
     689             : Licensed under the Apache License, Version 2.0 (the "License");
     690             : you may not use this file except in compliance with the License.
     691             : You may obtain a copy of the License at
     692             : 
     693             :     http://www.apache.org/licenses/LICENSE-2.0
     694             : 
     695             : Unless required by applicable law or agreed to in writing, software
     696             : distributed under the License is distributed on an "AS IS" BASIS,
     697             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     698             : See the License for the specific language governing permissions and
     699             : limitations under the License.
     700             : */

Generated by: LCOV version 1.16