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( ¤t_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( ¤t_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( ¤t_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( ¤t_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( ¤t_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( ¤t_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( ¤t_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( ¤t_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 : ctrl_undo_redo_iterator_t iter;
254 3 : ctrl_undo_redo_iterator_init_empty( &iter );
255 3 : result |= ctrl_controller_get_undo_iterator( (*this_).controller, &iter );
256 3 : ctrl_undo_redo_iterator_collect_statistics( &iter, false /* NOT categorize as undo */, io_stat );
257 3 : ctrl_undo_redo_iterator_destroy( &iter );
258 : }
259 :
260 3 : U8_TRACE_END_ERR( result );
261 3 : return result;
262 : }
263 :
264 : /* ================================ create elements without duplicate ids ================================ */
265 :
266 6 : u8_error_t ctrl_multi_step_changer_create_diagram ( ctrl_multi_step_changer_t *this_,
267 : data_diagram_t *new_diagram,
268 : u8_error_t* out_info )
269 : {
270 6 : U8_TRACE_BEGIN();
271 6 : assert( NULL != new_diagram );
272 6 : assert( NULL != out_info );
273 6 : u8_error_t result = U8_ERROR_NONE;
274 :
275 : /* ensure that a uuid exists */
276 6 : if ( 0 == utf8string_get_length( data_diagram_get_uuid_const( new_diagram ) ) )
277 : {
278 : data_uuid_t new_uuid;
279 0 : data_uuid_init_new( &new_uuid );
280 0 : data_diagram_set_uuid( new_diagram, data_uuid_get_string( &new_uuid ) );
281 0 : data_uuid_destroy( &new_uuid );
282 : }
283 :
284 : ctrl_diagram_controller_t *const diagram_ctrl
285 6 : = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
286 :
287 : data_row_id_t new_diagram_id;
288 : const u8_error_t create_err
289 6 : = ctrl_diagram_controller_create_diagram( diagram_ctrl,
290 : new_diagram,
291 : (*this_).is_first_step,
292 : &new_diagram_id
293 : );
294 6 : *out_info = create_err;
295 6 : if ( create_err == U8_ERROR_NONE )
296 : {
297 5 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
298 5 : data_diagram_set_row_id( new_diagram, new_diagram_id );
299 : }
300 1 : else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
301 : {
302 1 : data_diagram_set_row_id( new_diagram, DATA_ROW_ID_VOID );
303 : const u8_error_t alt_create_err
304 1 : = ctrl_diagram_controller_create_diagram( diagram_ctrl,
305 : new_diagram,
306 : (*this_).is_first_step,
307 : &new_diagram_id
308 : );
309 1 : if ( alt_create_err == U8_ERROR_NONE )
310 : {
311 1 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
312 1 : data_diagram_set_row_id( new_diagram, new_diagram_id );
313 1 : *out_info |= U8_ERROR_DUPLICATE_ID;
314 : }
315 : else
316 : {
317 0 : result = alt_create_err;
318 : }
319 : }
320 : else
321 : {
322 0 : result = create_err;
323 : }
324 :
325 6 : U8_TRACE_END_ERR( result );
326 6 : return result;
327 : }
328 :
329 16 : u8_error_t ctrl_multi_step_changer_create_diagramelement ( ctrl_multi_step_changer_t *this_,
330 : data_diagramelement_t *new_diagramelement,
331 : u8_error_t* out_info )
332 : {
333 16 : U8_TRACE_BEGIN();
334 16 : assert( NULL != new_diagramelement );
335 16 : assert( NULL != out_info );
336 16 : u8_error_t result = U8_ERROR_NONE;
337 :
338 : /* ensure that a uuid exists */
339 16 : if ( 0 == utf8string_get_length( data_diagramelement_get_uuid_const( new_diagramelement ) ) )
340 : {
341 : data_uuid_t new_uuid;
342 0 : data_uuid_init_new( &new_uuid );
343 0 : data_diagramelement_set_uuid( new_diagramelement, data_uuid_get_string( &new_uuid ) );
344 0 : data_uuid_destroy( &new_uuid );
345 : }
346 :
347 : ctrl_diagram_controller_t *const diagram_ctrl
348 16 : = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
349 :
350 : data_row_id_t new_diagramelement_id;
351 : const u8_error_t create_err
352 16 : = ctrl_diagram_controller_create_diagramelement( diagram_ctrl,
353 : new_diagramelement,
354 : (*this_).is_first_step,
355 : &new_diagramelement_id
356 : );
357 16 : *out_info = create_err;
358 16 : if ( create_err == U8_ERROR_NONE )
359 : {
360 16 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
361 16 : data_diagramelement_set_row_id( new_diagramelement, new_diagramelement_id );
362 : }
363 0 : else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
364 : {
365 0 : data_diagramelement_set_row_id( new_diagramelement, DATA_ROW_ID_VOID );
366 : const u8_error_t alt_create_err
367 0 : = ctrl_diagram_controller_create_diagramelement( diagram_ctrl,
368 : new_diagramelement,
369 : (*this_).is_first_step,
370 : &new_diagramelement_id
371 : );
372 0 : if ( alt_create_err == U8_ERROR_NONE )
373 : {
374 0 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
375 0 : data_diagramelement_set_row_id( new_diagramelement, new_diagramelement_id );
376 0 : *out_info |= U8_ERROR_DUPLICATE_ID;
377 : }
378 : else
379 : {
380 0 : result = alt_create_err;
381 : }
382 : }
383 : else
384 : {
385 0 : result = create_err;
386 : }
387 :
388 16 : U8_TRACE_END_ERR( result );
389 16 : return result;
390 : }
391 :
392 13 : u8_error_t ctrl_multi_step_changer_create_classifier ( ctrl_multi_step_changer_t *this_,
393 : data_classifier_t *new_classifier,
394 : u8_error_t* out_info )
395 : {
396 13 : U8_TRACE_BEGIN();
397 13 : assert( NULL != new_classifier );
398 13 : assert( NULL != out_info );
399 13 : u8_error_t result = U8_ERROR_NONE;
400 :
401 : /* ensure that a uuid exists */
402 13 : if ( 0 == utf8string_get_length( data_classifier_get_uuid_const( new_classifier ) ) )
403 : {
404 : data_uuid_t new_uuid;
405 0 : data_uuid_init_new( &new_uuid );
406 0 : data_classifier_set_uuid( new_classifier, data_uuid_get_string( &new_uuid ) );
407 0 : data_uuid_destroy( &new_uuid );
408 : }
409 :
410 : ctrl_classifier_controller_t *const classifier_ctrl
411 13 : = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
412 :
413 : data_row_id_t new_classifier_id;
414 : const u8_error_t create_err
415 13 : = ctrl_classifier_controller_create_classifier( classifier_ctrl,
416 : new_classifier,
417 : (*this_).is_first_step,
418 : &new_classifier_id
419 : );
420 13 : *out_info = create_err;
421 13 : if ( create_err == U8_ERROR_NONE )
422 : {
423 10 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
424 10 : data_classifier_set_row_id( new_classifier, new_classifier_id );
425 : }
426 3 : else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE ) )
427 : {
428 3 : data_classifier_set_row_id( new_classifier, DATA_ROW_ID_VOID );
429 : const u8_error_t alt_create_err
430 3 : = ctrl_classifier_controller_create_classifier( classifier_ctrl,
431 : new_classifier,
432 : (*this_).is_first_step,
433 : &new_classifier_id
434 : );
435 3 : if ( alt_create_err == U8_ERROR_NONE )
436 : {
437 0 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
438 0 : data_classifier_set_row_id( new_classifier, new_classifier_id );
439 0 : *out_info |= U8_ERROR_DUPLICATE_ID;
440 : }
441 : else
442 : {
443 3 : result = alt_create_err;
444 : }
445 : }
446 : else
447 : {
448 0 : result = create_err;
449 : }
450 :
451 13 : if ( u8_error_contains( result, U8_ERROR_DUPLICATE ) )
452 : {
453 3 : *out_info |= result;
454 3 : result = U8_ERROR_NONE;
455 :
456 : /* find an alternative, unused name */
457 : char wish_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
458 3 : utf8stringbuf_t wish_name = UTF8STRINGBUF( wish_name_buf );
459 3 : result |= utf8stringbuf_copy_str( wish_name, data_classifier_get_name_const( new_classifier ) ); /* error to be reported to caller */
460 : {
461 3 : bool name_ok = false;
462 : static const uint_fast16_t MAX_SEARCH_STEP = 10000;
463 : static const uint_fast16_t FIRST_STEP = 2;
464 7 : for ( uint_fast16_t search_step = FIRST_STEP; ( search_step < MAX_SEARCH_STEP )&&( ! name_ok )&&( result == U8_ERROR_NONE ); search_step ++ )
465 : {
466 : char new_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
467 4 : utf8stringbuf_t new_name = UTF8STRINGBUF( new_name_buf );
468 : const u8_error_t trunc_err
469 4 : = ctrl_multi_step_changer_private_propose_classifier_name( this_,
470 4 : utf8stringbuf_get_string( wish_name ),
471 : search_step,
472 : new_name
473 : );
474 4 : if ( trunc_err != U8_ERROR_NONE )
475 : {
476 0 : U8_TRACE_INFO_STR("Name truncated at search for alternative:", utf8stringbuf_get_string( new_name ) );
477 : }
478 4 : data_classifier_set_name( new_classifier, utf8stringbuf_get_string( new_name ) );
479 : const u8_error_t retry_err
480 4 : = ctrl_classifier_controller_create_classifier( classifier_ctrl,
481 : new_classifier,
482 : (*this_).is_first_step,
483 : &new_classifier_id
484 : );
485 4 : if ( u8_error_contains( retry_err, U8_ERROR_DUPLICATE ) )
486 : {
487 1 : *out_info |= retry_err;
488 : }
489 3 : else if ( retry_err == U8_ERROR_NONE )
490 : {
491 3 : name_ok = true; /* name unused */
492 3 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
493 3 : data_classifier_set_row_id( new_classifier, new_classifier_id );
494 3 : *out_info |= U8_ERROR_DUPLICATE_NAME;
495 : }
496 : else
497 : {
498 0 : result |= retry_err;
499 : }
500 : }
501 : }
502 : }
503 :
504 13 : U8_TRACE_END_ERR( result );
505 13 : return result;
506 : }
507 :
508 9 : u8_error_t ctrl_multi_step_changer_create_feature ( ctrl_multi_step_changer_t *this_,
509 : data_feature_t *new_feature,
510 : u8_error_t* out_info )
511 : {
512 9 : U8_TRACE_BEGIN();
513 9 : assert( NULL != new_feature );
514 9 : assert( NULL != out_info );
515 9 : u8_error_t result = U8_ERROR_NONE;
516 :
517 : /* ensure that a uuid exists */
518 9 : if ( 0 == utf8string_get_length( data_feature_get_uuid_const( new_feature ) ) )
519 : {
520 : data_uuid_t new_uuid;
521 0 : data_uuid_init_new( &new_uuid );
522 0 : data_feature_set_uuid( new_feature, data_uuid_get_string( &new_uuid ) );
523 0 : data_uuid_destroy( &new_uuid );
524 : }
525 :
526 : ctrl_classifier_controller_t *const classifier_ctrl
527 9 : = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
528 :
529 : data_row_id_t new_feature_id;
530 : const u8_error_t create_err
531 9 : = ctrl_classifier_controller_create_feature( classifier_ctrl,
532 : new_feature,
533 : (*this_).is_first_step,
534 : &new_feature_id
535 : );
536 9 : *out_info = create_err;
537 9 : if ( create_err == U8_ERROR_NONE )
538 : {
539 8 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
540 8 : data_feature_set_row_id( new_feature, new_feature_id );
541 : }
542 1 : else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE) )
543 : {
544 1 : data_feature_set_row_id( new_feature, DATA_ROW_ID_VOID );
545 : const u8_error_t alt_create_err
546 1 : = ctrl_classifier_controller_create_feature( classifier_ctrl,
547 : new_feature,
548 : (*this_).is_first_step,
549 : &new_feature_id
550 : );
551 1 : if ( alt_create_err == U8_ERROR_NONE )
552 : {
553 1 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
554 1 : data_feature_set_row_id( new_feature, new_feature_id );
555 1 : *out_info |= U8_ERROR_DUPLICATE_ID;
556 : }
557 : else
558 : {
559 0 : result = alt_create_err;
560 : }
561 : }
562 : else
563 : {
564 0 : result = create_err;
565 : }
566 :
567 9 : U8_TRACE_END_ERR( result );
568 9 : return result;
569 : }
570 :
571 7 : u8_error_t ctrl_multi_step_changer_create_relationship ( ctrl_multi_step_changer_t *this_,
572 : data_relationship_t *new_relationship,
573 : u8_error_t* out_info )
574 : {
575 7 : U8_TRACE_BEGIN();
576 7 : assert( NULL != new_relationship );
577 7 : assert( NULL != out_info );
578 7 : u8_error_t result = U8_ERROR_NONE;
579 :
580 : /* ensure that a uuid exists */
581 7 : if ( 0 == utf8string_get_length( data_relationship_get_uuid_const( new_relationship ) ) )
582 : {
583 : data_uuid_t new_uuid;
584 0 : data_uuid_init_new( &new_uuid );
585 0 : data_relationship_set_uuid( new_relationship, data_uuid_get_string( &new_uuid ) );
586 0 : data_uuid_destroy( &new_uuid );
587 : }
588 :
589 : ctrl_classifier_controller_t *const classifier_ctrl
590 7 : = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
591 :
592 : data_row_id_t new_relationship_id;
593 : const u8_error_t create_err
594 7 : = ctrl_classifier_controller_create_relationship( classifier_ctrl,
595 : new_relationship,
596 : (*this_).is_first_step,
597 : &new_relationship_id
598 : );
599 7 : *out_info = create_err;
600 7 : if ( create_err == U8_ERROR_NONE )
601 : {
602 5 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
603 5 : data_relationship_set_row_id( new_relationship, new_relationship_id );
604 : }
605 2 : else if ( u8_error_contains( create_err, U8_ERROR_DUPLICATE) )
606 : {
607 2 : data_relationship_set_row_id( new_relationship, DATA_ROW_ID_VOID );
608 : const u8_error_t alt_create_err
609 2 : = ctrl_classifier_controller_create_relationship( classifier_ctrl,
610 : new_relationship,
611 : (*this_).is_first_step,
612 : &new_relationship_id
613 : );
614 2 : if ( alt_create_err == U8_ERROR_NONE )
615 : {
616 2 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
617 2 : data_relationship_set_row_id( new_relationship, new_relationship_id );
618 2 : *out_info |= U8_ERROR_DUPLICATE_ID;
619 : }
620 : else
621 : {
622 0 : result = alt_create_err;
623 : }
624 : }
625 : else
626 : {
627 0 : result = create_err;
628 : }
629 :
630 7 : U8_TRACE_END_ERR( result );
631 7 : return result;
632 : }
633 :
634 : /* ================================ update links of existing elements ================================ */
635 :
636 0 : u8_error_t ctrl_multi_step_changer_update_diagram_parent_id ( ctrl_multi_step_changer_t *this_,
637 : data_row_id_t diagram_id,
638 : data_row_id_t new_diagram_parent_id )
639 : {
640 0 : U8_TRACE_BEGIN();
641 0 : u8_error_t result = U8_ERROR_NONE;
642 :
643 : ctrl_diagram_controller_t *const diagram_ctrl
644 0 : = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
645 :
646 0 : result = ctrl_diagram_controller_update_diagram_parent_id( diagram_ctrl,
647 : diagram_id,
648 : new_diagram_parent_id,
649 : (*this_).is_first_step
650 : );
651 0 : if ( result == U8_ERROR_NONE )
652 : {
653 0 : (*this_).is_first_step = CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND;
654 : }
655 :
656 0 : U8_TRACE_END_ERR( result );
657 0 : return result;
658 : }
659 :
660 : /* ================================ propose names of classifiers ================================ */
661 :
662 4 : u8_error_t ctrl_multi_step_changer_private_propose_classifier_name ( ctrl_multi_step_changer_t *this_,
663 : const char* base_classifier_name,
664 : uint_fast16_t iteration,
665 : utf8stringbuf_t out_name )
666 : {
667 4 : U8_TRACE_BEGIN();
668 4 : const size_t RESERVED_FOR_NUMBER = 5;
669 4 : assert( NULL != base_classifier_name );
670 4 : assert( utf8stringbuf_get_size(out_name) > RESERVED_FOR_NUMBER );
671 4 : u8_error_t result = U8_ERROR_NONE;
672 :
673 : /* find an alternative, unused name */
674 : /* copy the base_classifier_name to newname_buf */
675 : {
676 : utf8stringbuf_t shortened_new_name
677 4 : = utf8stringbuf_init( utf8stringbuf_get_size(out_name)-RESERVED_FOR_NUMBER, utf8stringbuf_get_string(out_name) );
678 4 : result |= utf8stringbuf_copy_str( shortened_new_name, base_classifier_name );
679 : /* null termination is guaranteed, also this function does not cut an utf8 code point in the middle. */
680 : }
681 : /* append a separator and the iteration number */
682 4 : result |= utf8stringbuf_append_str( out_name, "-" );
683 4 : result |= utf8stringbuf_append_int( out_name, iteration );
684 :
685 4 : U8_TRACE_END_ERR( result );
686 4 : return result;
687 : }
688 :
689 :
690 : /*
691 : Copyright 2016-2024 Andreas Warnke
692 :
693 : Licensed under the Apache License, Version 2.0 (the "License");
694 : you may not use this file except in compliance with the License.
695 : You may obtain a copy of the License at
696 :
697 : http://www.apache.org/licenses/LICENSE-2.0
698 :
699 : Unless required by applicable law or agreed to in writing, software
700 : distributed under the License is distributed on an "AS IS" BASIS,
701 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
702 : See the License for the specific language governing permissions and
703 : limitations under the License.
704 : */
|