Line data Source code
1 : /* File: ctrl_classifier_controller.c; Copyright and License: see below */
2 :
3 : #include "ctrl_classifier_controller.h"
4 : #include "u8/u8_trace.h"
5 : #include "u8/u8_log.h"
6 :
7 42 : void ctrl_classifier_controller_init ( ctrl_classifier_controller_t *this_,
8 : ctrl_undo_redo_list_t *undo_redo_list,
9 : ctrl_classifier_trigger_t *policy_enforcer,
10 : data_database_t *database,
11 : data_database_reader_t *db_reader,
12 : data_database_writer_t *db_writer )
13 : {
14 42 : U8_TRACE_BEGIN();
15 :
16 42 : (*this_).undo_redo_list = undo_redo_list;
17 42 : (*this_).policy_enforcer = policy_enforcer;
18 42 : (*this_).database = database;
19 42 : (*this_).db_reader = db_reader;
20 42 : (*this_).db_writer = db_writer;
21 42 : ctrl_consistency_checker_init ( &((*this_).consistency_checker), database, db_reader, db_writer );
22 :
23 42 : U8_TRACE_END();
24 42 : }
25 :
26 42 : void ctrl_classifier_controller_destroy ( ctrl_classifier_controller_t *this_ )
27 : {
28 42 : U8_TRACE_BEGIN();
29 :
30 42 : ctrl_consistency_checker_destroy ( &((*this_).consistency_checker) );
31 42 : (*this_).undo_redo_list = NULL;
32 42 : (*this_).policy_enforcer = NULL;
33 42 : (*this_).database = NULL;
34 42 : (*this_).db_reader = NULL;
35 42 : (*this_).db_writer = NULL;
36 :
37 42 : U8_TRACE_END();
38 42 : }
39 :
40 : /* ================================ CLASSIFIER ================================ */
41 :
42 33 : u8_error_t ctrl_classifier_controller_create_classifier ( ctrl_classifier_controller_t *this_,
43 : const data_classifier_t *new_classifier,
44 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set,
45 : data_row_t* out_new_id )
46 : {
47 33 : U8_TRACE_BEGIN();
48 33 : assert( NULL != new_classifier );
49 : data_classifier_t to_be_created;
50 33 : u8_error_t result = U8_ERROR_NONE;
51 : u8_error_t data_result;
52 : data_row_t new_id;
53 :
54 33 : data_classifier_copy( &to_be_created, new_classifier );
55 :
56 33 : data_result = data_database_writer_create_classifier( (*this_).db_writer, &to_be_created, &new_id );
57 33 : if ( U8_ERROR_NONE == data_result )
58 : {
59 : /* store new id to data_classifier_t object */
60 26 : data_classifier_set_row_id( &to_be_created, new_id );
61 :
62 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
63 26 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
64 : {
65 : u8_error_t internal_err;
66 9 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
67 9 : if ( U8_ERROR_NONE != internal_err )
68 : {
69 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
70 : }
71 : }
72 :
73 : /* store the new diagram to the undo redo list */
74 26 : ctrl_undo_redo_list_add_create_classifier( (*this_).undo_redo_list, &to_be_created );
75 26 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
76 :
77 : /* copy new id to out parameter */
78 26 : if ( NULL != out_new_id )
79 : {
80 26 : *out_new_id = new_id;
81 : }
82 : }
83 33 : result = data_result;
84 :
85 33 : data_classifier_destroy( &to_be_created );
86 :
87 33 : U8_TRACE_END_ERR( result );
88 33 : return result;
89 : }
90 :
91 7 : u8_error_t ctrl_classifier_controller_delete_classifier( ctrl_classifier_controller_t *this_,
92 : data_row_t obj_id,
93 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set )
94 : {
95 7 : U8_TRACE_BEGIN();
96 7 : u8_error_t result = U8_ERROR_NONE;
97 : u8_error_t data_result;
98 :
99 : /* check if the classifier is still referenced by diagramelements */
100 7 : bool is_still_referenced = true;
101 : {
102 : data_diagram_iterator_t diagram_iterator;
103 7 : result |= data_diagram_iterator_init_empty( &diagram_iterator );
104 7 : result |= data_database_reader_get_diagrams_by_classifier_id( (*this_).db_reader,
105 : obj_id,
106 : &diagram_iterator
107 : );
108 :
109 7 : if (( data_diagram_iterator_has_next( &diagram_iterator ) )||( result != U8_ERROR_NONE ))
110 : {
111 4 : is_still_referenced = true;
112 : }
113 : else
114 : {
115 3 : is_still_referenced = false;
116 : }
117 7 : result |= data_diagram_iterator_destroy( &diagram_iterator );
118 : }
119 :
120 : /* if the classifier is still referenced by diagramelements, do not do anything, report an error */
121 7 : if ( is_still_referenced )
122 : {
123 4 : result |= U8_ERROR_OBJECT_STILL_REFERENCED;
124 : }
125 : else
126 : {
127 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
128 3 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
129 : {
130 : u8_error_t internal_err;
131 3 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
132 3 : if ( U8_ERROR_NONE != internal_err )
133 : {
134 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
135 : }
136 : }
137 :
138 : /* delete all features */
139 : {
140 : data_feature_iterator_t feature_iterator;
141 3 : result |= data_feature_iterator_init_empty( &feature_iterator );
142 3 : result |= data_database_reader_get_features_by_classifier_id( (*this_).db_reader,
143 : obj_id,
144 : &feature_iterator
145 : );
146 3 : while ( data_feature_iterator_has_next( &feature_iterator ) )
147 : {
148 0 : result |= data_feature_iterator_next( &feature_iterator, &((*this_).temp_feature) );
149 0 : const data_row_t feat_id = data_feature_get_row_id( &((*this_).temp_feature) );
150 0 : data_result = data_database_writer_delete_feature( (*this_).db_writer, feat_id, NULL );
151 0 : if ( data_result == U8_ERROR_NONE )
152 : {
153 : /* store the deleted feature to the undo redo list */
154 0 : ctrl_undo_redo_list_add_delete_feature( (*this_).undo_redo_list, &((*this_).temp_feature) );
155 : }
156 : else
157 : {
158 : /* report this unexpected error */
159 0 : result |= data_result;
160 : }
161 0 : data_feature_destroy( &((*this_).temp_feature) );
162 : }
163 3 : result |= data_feature_iterator_destroy( &feature_iterator );
164 : }
165 :
166 : /* delete all relationships */
167 : {
168 : data_relationship_iterator_t relationship_iterator;
169 3 : result |= data_relationship_iterator_init_empty( &relationship_iterator );
170 3 : result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
171 : obj_id,
172 : &relationship_iterator
173 : );
174 3 : while ( data_relationship_iterator_has_next( &relationship_iterator ) )
175 : {
176 0 : result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship) );
177 0 : const data_row_t rel_id = data_relationship_get_row_id( &((*this_).temp_relationship) );
178 0 : data_result = data_database_writer_delete_relationship( (*this_).db_writer, rel_id, NULL );
179 0 : if ( data_result == U8_ERROR_NONE )
180 : {
181 : /* store the deleted relationship to the undo redo list */
182 0 : ctrl_undo_redo_list_add_delete_relationship( (*this_).undo_redo_list, &((*this_).temp_relationship) );
183 : }
184 : else
185 : {
186 : /* report this unexpected error */
187 0 : result |= data_result;
188 : }
189 0 : data_relationship_destroy( &((*this_).temp_relationship) );
190 : }
191 3 : result |= data_relationship_iterator_destroy( &relationship_iterator );
192 : }
193 :
194 : /* delete the classifier */
195 : {
196 : data_classifier_t old_classifier;
197 3 : data_result = data_database_writer_delete_classifier( (*this_).db_writer,
198 : obj_id,
199 : &old_classifier
200 : );
201 :
202 3 : if ( U8_ERROR_NONE == data_result )
203 : {
204 : /* store the deleted classifier to the undo redo list */
205 3 : ctrl_undo_redo_list_add_delete_classifier( (*this_).undo_redo_list, &old_classifier );
206 :
207 3 : data_classifier_destroy( &old_classifier );
208 : }
209 0 : else if ( u8_error_contains( data_result, U8_ERROR_OBJECT_STILL_REFERENCED ) )
210 : {
211 : /* report this unexpected error */
212 0 : U8_LOG_ERROR( "The classifier cannot be deleted because it is still referenced." );
213 0 : result |= data_result;
214 : }
215 : else
216 : {
217 : /* report this unexpected error */
218 0 : result |= data_result;
219 : }
220 : }
221 :
222 : /* add a boundary to the undo redo list */
223 3 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
224 : }
225 :
226 7 : U8_TRACE_END_ERR( result );
227 7 : return result;
228 : }
229 :
230 1 : u8_error_t ctrl_classifier_controller_update_classifier_main_type ( ctrl_classifier_controller_t *this_,
231 : data_row_t classifier_id,
232 : data_classifier_type_t new_classifier_main_type )
233 : {
234 1 : U8_TRACE_BEGIN();
235 1 : u8_error_t result = U8_ERROR_NONE;
236 : u8_error_t data_result;
237 : data_classifier_t old_classifier;
238 :
239 1 : data_result = data_database_writer_update_classifier_main_type( (*this_).db_writer, classifier_id, new_classifier_main_type, &old_classifier );
240 1 : if ( U8_ERROR_NONE == data_result )
241 : {
242 : /* prepare the new classifier */
243 : data_classifier_t new_classifier;
244 1 : data_classifier_copy( &new_classifier, &old_classifier );
245 1 : data_classifier_set_main_type( &new_classifier, new_classifier_main_type );
246 : /* store the change of the classifier to the undo redo list */
247 1 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
248 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
249 :
250 1 : data_classifier_destroy( &new_classifier );
251 1 : data_classifier_destroy( &old_classifier );
252 : }
253 1 : result = data_result;
254 :
255 1 : U8_TRACE_END_ERR( result );
256 1 : return result;
257 : }
258 :
259 2 : u8_error_t ctrl_classifier_controller_update_classifier_stereotype ( ctrl_classifier_controller_t *this_,
260 : data_row_t classifier_id,
261 : const char* new_classifier_stereotype )
262 : {
263 2 : U8_TRACE_BEGIN();
264 2 : u8_error_t result = U8_ERROR_NONE;
265 : u8_error_t data_result;
266 : data_classifier_t old_classifier;
267 :
268 2 : data_result = data_database_writer_update_classifier_stereotype( (*this_).db_writer, classifier_id, new_classifier_stereotype, &old_classifier );
269 2 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
270 : {
271 : /* prepare the new classifier */
272 : data_classifier_t new_classifier;
273 2 : data_classifier_copy( &new_classifier, &old_classifier );
274 2 : data_classifier_set_stereotype( &new_classifier, new_classifier_stereotype );
275 : /* store the change of the classifier to the undo redo list */
276 2 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
277 2 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
278 :
279 2 : data_classifier_destroy( &new_classifier );
280 2 : data_classifier_destroy( &old_classifier );
281 : }
282 2 : result = data_result;
283 :
284 2 : U8_TRACE_END_ERR( result );
285 2 : return result;
286 : }
287 :
288 1 : u8_error_t ctrl_classifier_controller_update_classifier_name ( ctrl_classifier_controller_t *this_,
289 : data_row_t classifier_id,
290 : const char* new_classifier_name )
291 : {
292 1 : U8_TRACE_BEGIN();
293 1 : u8_error_t result = U8_ERROR_NONE;
294 : u8_error_t data_result;
295 : data_classifier_t old_classifier;
296 :
297 1 : data_result = data_database_writer_update_classifier_name( (*this_).db_writer, classifier_id, new_classifier_name, &old_classifier );
298 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
299 : {
300 : /* prepare the new classifier */
301 : data_classifier_t new_classifier;
302 1 : data_classifier_copy( &new_classifier, &old_classifier );
303 1 : data_classifier_set_name( &new_classifier, new_classifier_name );
304 : /* store the change of the classifier to the undo redo list */
305 1 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
306 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
307 :
308 1 : data_classifier_destroy( &new_classifier );
309 1 : data_classifier_destroy( &old_classifier );
310 : }
311 1 : result = data_result;
312 :
313 1 : U8_TRACE_END_ERR( result );
314 1 : return result;
315 : }
316 :
317 1 : u8_error_t ctrl_classifier_controller_update_classifier_description ( ctrl_classifier_controller_t *this_,
318 : data_row_t classifier_id,
319 : const char* new_classifier_description )
320 : {
321 1 : U8_TRACE_BEGIN();
322 1 : u8_error_t result = U8_ERROR_NONE;
323 : u8_error_t data_result;
324 : data_classifier_t old_classifier;
325 :
326 1 : data_result = data_database_writer_update_classifier_description( (*this_).db_writer, classifier_id, new_classifier_description, &old_classifier );
327 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
328 : {
329 : /* prepare the new classifier */
330 : data_classifier_t new_classifier;
331 1 : data_classifier_copy( &new_classifier, &old_classifier );
332 1 : data_classifier_set_description( &new_classifier, new_classifier_description );
333 : /* store the change of the classifier to the undo redo list */
334 1 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
335 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
336 :
337 1 : data_classifier_destroy( &new_classifier );
338 1 : data_classifier_destroy( &old_classifier );
339 : }
340 1 : result = data_result;
341 :
342 1 : U8_TRACE_END_ERR( result );
343 1 : return result;
344 : }
345 :
346 1 : u8_error_t ctrl_classifier_controller_update_classifier_x_order ( ctrl_classifier_controller_t *this_,
347 : data_row_t classifier_id,
348 : int32_t new_classifier_x_order )
349 : {
350 1 : U8_TRACE_BEGIN();
351 1 : u8_error_t result = U8_ERROR_NONE;
352 : u8_error_t data_result;
353 : data_classifier_t old_classifier;
354 :
355 1 : data_result = data_database_writer_update_classifier_x_order( (*this_).db_writer, classifier_id, new_classifier_x_order, &old_classifier );
356 1 : if ( U8_ERROR_NONE == data_result )
357 : {
358 : /* prepare the new classifier */
359 : data_classifier_t new_classifier;
360 1 : data_classifier_copy( &new_classifier, &old_classifier );
361 1 : data_classifier_set_x_order( &new_classifier, new_classifier_x_order );
362 : /* store the change of the classifier to the undo redo list */
363 1 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
364 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
365 :
366 1 : data_classifier_destroy( &new_classifier );
367 1 : data_classifier_destroy( &old_classifier );
368 : }
369 1 : result = data_result;
370 :
371 1 : U8_TRACE_END_ERR( result );
372 1 : return result;
373 : }
374 :
375 1 : u8_error_t ctrl_classifier_controller_update_classifier_y_order ( ctrl_classifier_controller_t *this_,
376 : data_row_t classifier_id,
377 : int32_t new_classifier_y_order )
378 : {
379 1 : U8_TRACE_BEGIN();
380 1 : u8_error_t result = U8_ERROR_NONE;
381 : u8_error_t data_result;
382 : data_classifier_t old_classifier;
383 :
384 1 : data_result = data_database_writer_update_classifier_y_order( (*this_).db_writer, classifier_id, new_classifier_y_order, &old_classifier );
385 1 : if ( U8_ERROR_NONE == data_result )
386 : {
387 : /* prepare the new classifier */
388 : data_classifier_t new_classifier;
389 1 : data_classifier_copy( &new_classifier, &old_classifier );
390 1 : data_classifier_set_y_order( &new_classifier, new_classifier_y_order );
391 : /* store the change of the classifier to the undo redo list */
392 1 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
393 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
394 :
395 1 : data_classifier_destroy( &new_classifier );
396 1 : data_classifier_destroy( &old_classifier );
397 : }
398 1 : result = data_result;
399 :
400 1 : U8_TRACE_END_ERR( result );
401 1 : return result;
402 : }
403 :
404 0 : u8_error_t ctrl_classifier_controller_update_classifier_x_order_y_order ( ctrl_classifier_controller_t *this_,
405 : data_row_t classifier_id,
406 : int32_t new_classifier_x_order,
407 : int32_t new_classifier_y_order )
408 : {
409 0 : U8_TRACE_BEGIN();
410 0 : u8_error_t result = U8_ERROR_NONE;
411 : u8_error_t data_result;
412 : data_classifier_t old_classifier;
413 :
414 0 : data_result = data_database_writer_update_classifier_x_order( (*this_).db_writer, classifier_id, new_classifier_x_order, &old_classifier );
415 0 : if ( U8_ERROR_NONE == data_result )
416 : {
417 0 : data_result = data_database_writer_update_classifier_y_order( (*this_).db_writer, classifier_id, new_classifier_y_order, NULL );
418 0 : if ( U8_ERROR_NONE == data_result )
419 : {
420 : /* prepare the new classifier */
421 : data_classifier_t new_classifier;
422 0 : data_classifier_copy( &new_classifier, &old_classifier );
423 0 : data_classifier_set_x_order( &new_classifier, new_classifier_x_order );
424 0 : data_classifier_set_y_order( &new_classifier, new_classifier_y_order );
425 : /* store the change of the classifier to the undo redo list */
426 0 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
427 0 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
428 :
429 0 : data_classifier_destroy( &new_classifier );
430 : }
431 0 : data_classifier_destroy( &old_classifier );
432 : }
433 0 : result = data_result;
434 :
435 0 : U8_TRACE_END_ERR( result );
436 0 : return result;
437 : }
438 :
439 0 : u8_error_t ctrl_classifier_controller_update_classifier_list_order ( ctrl_classifier_controller_t *this_,
440 : data_row_t classifier_id,
441 : int32_t new_classifier_list_order )
442 : {
443 0 : U8_TRACE_BEGIN();
444 0 : u8_error_t result = U8_ERROR_NONE;
445 : u8_error_t data_result;
446 : data_classifier_t old_classifier;
447 :
448 0 : data_result = data_database_writer_update_classifier_list_order( (*this_).db_writer, classifier_id, new_classifier_list_order, &old_classifier );
449 0 : if ( U8_ERROR_NONE == data_result )
450 : {
451 : /* prepare the new classifier */
452 : data_classifier_t new_classifier;
453 0 : data_classifier_copy( &new_classifier, &old_classifier );
454 0 : data_classifier_set_list_order( &new_classifier, new_classifier_list_order );
455 : /* store the change of the classifier to the undo redo list */
456 0 : ctrl_undo_redo_list_add_update_classifier( (*this_).undo_redo_list, &old_classifier, &new_classifier );
457 0 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
458 :
459 0 : data_classifier_destroy( &new_classifier );
460 0 : data_classifier_destroy( &old_classifier );
461 : }
462 0 : result = data_result;
463 :
464 0 : U8_TRACE_END_ERR( result );
465 0 : return result;
466 : }
467 :
468 : /* ================================ FEATURE ================================ */
469 :
470 33 : u8_error_t ctrl_classifier_controller_create_feature ( ctrl_classifier_controller_t *this_,
471 : const data_feature_t *new_feature,
472 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set,
473 : data_row_t* out_new_id )
474 : {
475 33 : U8_TRACE_BEGIN();
476 33 : assert( NULL != new_feature );
477 : data_feature_t to_be_created;
478 33 : u8_error_t result = U8_ERROR_NONE;
479 : u8_error_t data_result;
480 : data_row_t new_id;
481 :
482 33 : data_feature_copy( &to_be_created, new_feature );
483 :
484 33 : data_result = data_database_writer_create_feature( (*this_).db_writer, &to_be_created, &new_id );
485 33 : if ( U8_ERROR_NONE == data_result )
486 : {
487 : /* store new id to data_feature_t object */
488 32 : data_feature_set_row_id( &to_be_created, new_id );
489 :
490 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
491 32 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
492 : {
493 : u8_error_t internal_err;
494 27 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
495 27 : if ( U8_ERROR_NONE != internal_err )
496 : {
497 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
498 : }
499 : }
500 :
501 : /* store the new feature to the undo redo list */
502 32 : ctrl_undo_redo_list_add_create_feature( (*this_).undo_redo_list, &to_be_created );
503 32 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
504 :
505 : /* copy new id to out parameter */
506 32 : if ( NULL != out_new_id )
507 : {
508 32 : *out_new_id = new_id;
509 : }
510 : }
511 33 : result = data_result;
512 :
513 33 : data_feature_destroy( &to_be_created );
514 :
515 33 : U8_TRACE_END_ERR( result );
516 33 : return result;
517 : }
518 :
519 10 : u8_error_t ctrl_classifier_controller_delete_feature ( ctrl_classifier_controller_t *this_,
520 : data_row_t obj_id,
521 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set )
522 : {
523 10 : U8_TRACE_BEGIN();
524 10 : u8_error_t result = U8_ERROR_NONE;
525 : u8_error_t data_result;
526 :
527 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
528 10 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
529 : {
530 : u8_error_t internal_err;
531 5 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
532 5 : if ( U8_ERROR_NONE != internal_err )
533 : {
534 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
535 : }
536 : }
537 :
538 : /* delete all relationships to and/or from this feature */
539 : {
540 : data_relationship_iterator_t relationship_iterator;
541 10 : result |= data_relationship_iterator_init_empty( &relationship_iterator );
542 10 : result |= data_database_reader_get_relationships_by_feature_id( (*this_).db_reader,
543 : obj_id,
544 : &relationship_iterator
545 : );
546 11 : while ( data_relationship_iterator_has_next( &relationship_iterator ) )
547 : {
548 1 : result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship) );
549 1 : const data_row_t rel_id = data_relationship_get_row_id( &((*this_).temp_relationship) );
550 1 : data_result = data_database_writer_delete_relationship( (*this_).db_writer, rel_id, NULL );
551 1 : if ( U8_ERROR_NONE == data_result )
552 : {
553 : /* store the deleted relationship to the undo redo list */
554 1 : ctrl_undo_redo_list_add_delete_relationship( (*this_).undo_redo_list, &((*this_).temp_relationship) );
555 : }
556 : else
557 : {
558 : /* report this unexpected error */
559 0 : result |= data_result;
560 : }
561 1 : data_relationship_destroy( &((*this_).temp_relationship) );
562 : }
563 10 : result |= data_relationship_iterator_destroy( &relationship_iterator );
564 : }
565 :
566 : /* delete the feature */
567 : data_feature_t old_feature;
568 : u8_error_t feature_result;
569 : {
570 : /* delete feature */
571 10 : feature_result = data_database_writer_delete_feature( (*this_).db_writer, obj_id, &old_feature );
572 :
573 10 : if ( U8_ERROR_NONE == feature_result )
574 : {
575 : /* store the deleted feature to the undo redo list */
576 9 : ctrl_undo_redo_list_add_delete_feature( (*this_).undo_redo_list, &old_feature );
577 : }
578 :
579 10 : result |= feature_result;
580 : }
581 :
582 : /* add boundary to undo-redo-list */
583 10 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
584 :
585 : /* apply policy rules */
586 10 : if ( U8_ERROR_NONE == feature_result )
587 : {
588 9 : result |= ctrl_classifier_trigger_post_delete_feature ( (*this_).policy_enforcer, &old_feature );
589 9 : data_feature_destroy( &old_feature );
590 : }
591 :
592 10 : U8_TRACE_END_ERR( result );
593 10 : return result;
594 : }
595 :
596 2 : u8_error_t ctrl_classifier_controller_update_feature_main_type ( ctrl_classifier_controller_t *this_,
597 : data_row_t feature_id,
598 : data_feature_type_t new_feature_type )
599 : {
600 2 : U8_TRACE_BEGIN();
601 2 : u8_error_t result = U8_ERROR_NONE;
602 : u8_error_t data_result;
603 : data_feature_t old_feature;
604 :
605 2 : data_result = data_database_writer_update_feature_main_type( (*this_).db_writer, feature_id, new_feature_type, &old_feature );
606 2 : if ( U8_ERROR_NONE == data_result )
607 : {
608 : /* prepare the new feature */
609 : data_feature_t new_feature;
610 2 : data_feature_copy( &new_feature, &old_feature );
611 2 : data_feature_set_main_type( &new_feature, new_feature_type );
612 : /* store the change of the feature to the undo redo list */
613 2 : ctrl_undo_redo_list_add_update_feature( (*this_).undo_redo_list, &old_feature, &new_feature );
614 2 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
615 :
616 2 : data_feature_destroy( &new_feature );
617 2 : data_feature_destroy( &old_feature );
618 : }
619 2 : result = data_result;
620 :
621 2 : U8_TRACE_END_ERR( result );
622 2 : return result;
623 : }
624 :
625 1 : u8_error_t ctrl_classifier_controller_update_feature_key ( ctrl_classifier_controller_t *this_,
626 : data_row_t feature_id,
627 : const char* new_feature_key )
628 : {
629 1 : U8_TRACE_BEGIN();
630 1 : u8_error_t result = U8_ERROR_NONE;
631 : u8_error_t data_result;
632 : data_feature_t old_feature;
633 :
634 1 : data_result = data_database_writer_update_feature_key( (*this_).db_writer, feature_id, new_feature_key, &old_feature );
635 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
636 : {
637 : /* prepare the new feature */
638 : data_feature_t new_feature;
639 1 : data_feature_copy( &new_feature, &old_feature );
640 1 : data_feature_set_key( &new_feature, new_feature_key );
641 : /* store the change of the feature to the undo redo list */
642 1 : ctrl_undo_redo_list_add_update_feature( (*this_).undo_redo_list, &old_feature, &new_feature );
643 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
644 :
645 1 : data_feature_destroy( &new_feature );
646 1 : data_feature_destroy( &old_feature );
647 : }
648 1 : result = data_result;
649 :
650 1 : U8_TRACE_END_ERR( result );
651 1 : return result;
652 : }
653 :
654 2 : u8_error_t ctrl_classifier_controller_update_feature_value ( ctrl_classifier_controller_t *this_,
655 : data_row_t feature_id,
656 : const char* new_feature_value )
657 : {
658 2 : U8_TRACE_BEGIN();
659 2 : u8_error_t result = U8_ERROR_NONE;
660 : u8_error_t data_result;
661 : data_feature_t old_feature;
662 :
663 2 : data_result = data_database_writer_update_feature_value( (*this_).db_writer, feature_id, new_feature_value, &old_feature );
664 2 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
665 : {
666 : /* prepare the new feature */
667 : data_feature_t new_feature;
668 2 : data_feature_copy( &new_feature, &old_feature );
669 2 : data_feature_set_value( &new_feature, new_feature_value );
670 : /* store the change of the feature to the undo redo list */
671 2 : ctrl_undo_redo_list_add_update_feature( (*this_).undo_redo_list, &old_feature, &new_feature );
672 2 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
673 :
674 2 : data_feature_destroy( &new_feature );
675 2 : data_feature_destroy( &old_feature );
676 : }
677 2 : result = data_result;
678 :
679 2 : U8_TRACE_END_ERR( result );
680 2 : return result;
681 : }
682 :
683 1 : u8_error_t ctrl_classifier_controller_update_feature_description ( ctrl_classifier_controller_t *this_,
684 : data_row_t feature_id,
685 : const char* new_feature_description )
686 : {
687 1 : U8_TRACE_BEGIN();
688 1 : u8_error_t result = U8_ERROR_NONE;
689 : u8_error_t data_result;
690 : data_feature_t old_feature;
691 :
692 1 : data_result = data_database_writer_update_feature_description( (*this_).db_writer, feature_id, new_feature_description, &old_feature );
693 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
694 : {
695 : /* prepare the new feature */
696 : data_feature_t new_feature;
697 1 : data_feature_copy( &new_feature, &old_feature );
698 1 : data_feature_set_description( &new_feature, new_feature_description );
699 : /* store the change of the feature to the undo redo list */
700 1 : ctrl_undo_redo_list_add_update_feature( (*this_).undo_redo_list, &old_feature, &new_feature );
701 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
702 :
703 1 : data_feature_destroy( &new_feature );
704 1 : data_feature_destroy( &old_feature );
705 : }
706 1 : result = data_result;
707 :
708 1 : U8_TRACE_END_ERR( result );
709 1 : return result;
710 : }
711 :
712 1 : u8_error_t ctrl_classifier_controller_update_feature_list_order ( ctrl_classifier_controller_t *this_,
713 : data_row_t feature_id,
714 : int32_t new_feature_list_order )
715 : {
716 1 : U8_TRACE_BEGIN();
717 1 : u8_error_t result = U8_ERROR_NONE;
718 : u8_error_t data_result;
719 : data_feature_t old_feature;
720 :
721 1 : data_result = data_database_writer_update_feature_list_order( (*this_).db_writer, feature_id, new_feature_list_order, &old_feature );
722 1 : if ( U8_ERROR_NONE == data_result )
723 : {
724 : /* prepare the new feature */
725 : data_feature_t new_feature;
726 1 : data_feature_copy( &new_feature, &old_feature );
727 1 : data_feature_set_list_order( &new_feature, new_feature_list_order );
728 : /* store the change of the feature to the undo redo list */
729 1 : ctrl_undo_redo_list_add_update_feature( (*this_).undo_redo_list, &old_feature, &new_feature );
730 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
731 :
732 1 : data_feature_destroy( &new_feature );
733 1 : data_feature_destroy( &old_feature );
734 : }
735 1 : result = data_result;
736 :
737 1 : U8_TRACE_END_ERR( result );
738 1 : return result;
739 : }
740 :
741 : /* ================================ RELATIONSHIP ================================ */
742 :
743 15 : u8_error_t ctrl_classifier_controller_create_relationship ( ctrl_classifier_controller_t *this_,
744 : const data_relationship_t *new_relationship,
745 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set,
746 : data_row_t* out_new_id )
747 : {
748 15 : U8_TRACE_BEGIN();
749 15 : assert( NULL != new_relationship );
750 : data_relationship_t to_be_created;
751 15 : u8_error_t result = U8_ERROR_NONE;
752 : u8_error_t data_result;
753 : data_row_t new_id;
754 :
755 15 : data_relationship_copy( &to_be_created, new_relationship );
756 :
757 15 : data_result = data_database_writer_create_relationship( (*this_).db_writer, &to_be_created, &new_id );
758 15 : if ( U8_ERROR_NONE == data_result )
759 : {
760 : /* store new id to data_relationship_t object */
761 13 : data_relationship_set_row_id( &to_be_created, new_id );
762 :
763 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
764 13 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
765 : {
766 : u8_error_t internal_err;
767 7 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
768 7 : if ( U8_ERROR_NONE != internal_err )
769 : {
770 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
771 : }
772 : }
773 :
774 : /* store the new relationship to the undo redo list */
775 13 : ctrl_undo_redo_list_add_create_relationship( (*this_).undo_redo_list, &to_be_created );
776 13 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
777 :
778 : /* copy new id to out parameter */
779 13 : if ( NULL != out_new_id )
780 : {
781 13 : *out_new_id = new_id;
782 : }
783 : }
784 15 : result = data_result;
785 :
786 15 : data_relationship_destroy( &to_be_created );
787 :
788 15 : U8_TRACE_END_ERR( result );
789 15 : return result;
790 : }
791 :
792 5 : u8_error_t ctrl_classifier_controller_delete_relationship ( ctrl_classifier_controller_t *this_,
793 : data_row_t obj_id,
794 : ctrl_undo_redo_action_boundary_t add_to_latest_undo_set )
795 : {
796 5 : U8_TRACE_BEGIN();
797 5 : u8_error_t result = U8_ERROR_NONE;
798 :
799 : /* delete relationship */
800 : data_relationship_t old_relation;
801 : u8_error_t current_result5;
802 5 : current_result5 = data_database_writer_delete_relationship( (*this_).db_writer, obj_id, &old_relation );
803 :
804 5 : if ( U8_ERROR_NONE == current_result5 )
805 : {
806 : /* if this action shall be stored to the latest set of actions in the undo redo list, remove the boundary: */
807 4 : if ( add_to_latest_undo_set == CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
808 : {
809 : u8_error_t internal_err;
810 3 : internal_err = ctrl_undo_redo_list_remove_boundary_from_end( (*this_).undo_redo_list );
811 3 : if ( U8_ERROR_NONE != internal_err )
812 : {
813 0 : U8_LOG_ERROR_HEX( "unexpected internal error", internal_err );
814 : }
815 : }
816 :
817 : /* store the deleted relationship to the undo redo list */
818 4 : ctrl_undo_redo_list_add_delete_relationship( (*this_).undo_redo_list, &old_relation );
819 4 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
820 :
821 4 : data_relationship_destroy( &old_relation );
822 : }
823 :
824 5 : result |= current_result5;
825 :
826 5 : U8_TRACE_END_ERR( result );
827 5 : return result;
828 : }
829 :
830 1 : u8_error_t ctrl_classifier_controller_update_relationship_main_type ( ctrl_classifier_controller_t *this_,
831 : data_row_t relationship_id,
832 : data_relationship_type_t new_relationship_type )
833 : {
834 1 : U8_TRACE_BEGIN();
835 1 : u8_error_t result = U8_ERROR_NONE;
836 : u8_error_t data_result;
837 : data_relationship_t old_relation;
838 :
839 1 : data_result = data_database_writer_update_relationship_main_type( (*this_).db_writer, relationship_id, new_relationship_type, &old_relation );
840 1 : if ( U8_ERROR_NONE == data_result )
841 : {
842 : /* prepare the new relation */
843 : data_relationship_t new_relation;
844 1 : data_relationship_copy( &new_relation, &old_relation );
845 1 : data_relationship_set_main_type( &new_relation, new_relationship_type );
846 : /* store the change of the relation to the undo redo list */
847 1 : ctrl_undo_redo_list_add_update_relationship( (*this_).undo_redo_list, &old_relation, &new_relation );
848 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
849 :
850 1 : data_relationship_destroy( &new_relation );
851 1 : data_relationship_destroy( &old_relation );
852 : }
853 1 : result = data_result;
854 :
855 1 : U8_TRACE_END_ERR( result );
856 1 : return result;
857 : }
858 :
859 1 : u8_error_t ctrl_classifier_controller_update_relationship_stereotype ( ctrl_classifier_controller_t *this_,
860 : data_row_t relationship_id,
861 : const char* new_relationship_stereotype )
862 : {
863 1 : U8_TRACE_BEGIN();
864 1 : u8_error_t result = U8_ERROR_NONE;
865 : u8_error_t data_result;
866 : data_relationship_t old_relation;
867 :
868 1 : data_result = data_database_writer_update_relationship_stereotype( (*this_).db_writer, relationship_id, new_relationship_stereotype, &old_relation );
869 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
870 : {
871 : /* prepare the new relation */
872 : data_relationship_t new_relation;
873 1 : data_relationship_copy( &new_relation, &old_relation );
874 1 : data_relationship_set_stereotype( &new_relation, new_relationship_stereotype );
875 : /* store the change of the relation to the undo redo list */
876 1 : ctrl_undo_redo_list_add_update_relationship( (*this_).undo_redo_list, &old_relation, &new_relation );
877 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
878 :
879 1 : data_relationship_destroy( &new_relation );
880 1 : data_relationship_destroy( &old_relation );
881 : }
882 1 : result = data_result;
883 :
884 1 : U8_TRACE_END_ERR( result );
885 1 : return result;
886 : }
887 :
888 1 : u8_error_t ctrl_classifier_controller_update_relationship_name ( ctrl_classifier_controller_t *this_,
889 : data_row_t relationship_id,
890 : const char* new_relationship_name )
891 : {
892 1 : U8_TRACE_BEGIN();
893 1 : u8_error_t result = U8_ERROR_NONE;
894 : u8_error_t data_result;
895 : data_relationship_t old_relation;
896 :
897 1 : data_result = data_database_writer_update_relationship_name( (*this_).db_writer, relationship_id, new_relationship_name, &old_relation );
898 1 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
899 : {
900 : /* prepare the new relation */
901 : data_relationship_t new_relation;
902 1 : data_relationship_copy( &new_relation, &old_relation );
903 1 : data_relationship_set_name( &new_relation, new_relationship_name );
904 : /* store the change of the relation to the undo redo list */
905 1 : ctrl_undo_redo_list_add_update_relationship( (*this_).undo_redo_list, &old_relation, &new_relation );
906 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
907 :
908 1 : data_relationship_destroy( &new_relation );
909 1 : data_relationship_destroy( &old_relation );
910 : }
911 1 : result = data_result;
912 :
913 1 : U8_TRACE_END_ERR( result );
914 1 : return result;
915 : }
916 :
917 2 : u8_error_t ctrl_classifier_controller_update_relationship_description ( ctrl_classifier_controller_t *this_,
918 : data_row_t relationship_id,
919 : const char* new_relationship_description )
920 : {
921 2 : U8_TRACE_BEGIN();
922 2 : u8_error_t result = U8_ERROR_NONE;
923 : u8_error_t data_result;
924 : data_relationship_t old_relation;
925 :
926 2 : data_result = data_database_writer_update_relationship_description( (*this_).db_writer, relationship_id, new_relationship_description, &old_relation );
927 2 : if (( U8_ERROR_NONE == data_result ) || ( U8_ERROR_STRING_BUFFER_EXCEEDED == data_result ))
928 : {
929 : /* prepare the new relation */
930 : data_relationship_t new_relation;
931 2 : data_relationship_copy( &new_relation, &old_relation );
932 2 : data_relationship_set_description( &new_relation, new_relationship_description );
933 : /* store the change of the relation to the undo redo list */
934 2 : ctrl_undo_redo_list_add_update_relationship( (*this_).undo_redo_list, &old_relation, &new_relation );
935 2 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
936 :
937 2 : data_relationship_destroy( &new_relation );
938 2 : data_relationship_destroy( &old_relation );
939 : }
940 2 : result = data_result;
941 :
942 2 : U8_TRACE_END_ERR( result );
943 2 : return result;
944 : }
945 :
946 1 : u8_error_t ctrl_classifier_controller_update_relationship_list_order ( ctrl_classifier_controller_t *this_,
947 : data_row_t relationship_id,
948 : int32_t new_relationship_list_order )
949 : {
950 1 : U8_TRACE_BEGIN();
951 1 : u8_error_t result = U8_ERROR_NONE;
952 : u8_error_t data_result;
953 : data_relationship_t old_relation;
954 :
955 1 : data_result = data_database_writer_update_relationship_list_order( (*this_).db_writer, relationship_id, new_relationship_list_order, &old_relation );
956 1 : if ( U8_ERROR_NONE == data_result )
957 : {
958 : /* prepare the new relation */
959 : data_relationship_t new_relation;
960 1 : data_relationship_copy( &new_relation, &old_relation );
961 1 : data_relationship_set_list_order( &new_relation, new_relationship_list_order );
962 : /* store the change of the relation to the undo redo list */
963 1 : ctrl_undo_redo_list_add_update_relationship( (*this_).undo_redo_list, &old_relation, &new_relation );
964 1 : ctrl_undo_redo_list_add_boundary( (*this_).undo_redo_list );
965 :
966 1 : data_relationship_destroy( &new_relation );
967 1 : data_relationship_destroy( &old_relation );
968 : }
969 1 : result = data_result;
970 :
971 1 : U8_TRACE_END_ERR( result );
972 1 : return result;
973 : }
974 :
975 :
976 : /*
977 : Copyright 2016-2024 Andreas Warnke
978 :
979 : Licensed under the Apache License, Version 2.0 (the "License");
980 : you may not use this file except in compliance with the License.
981 : You may obtain a copy of the License at
982 :
983 : http://www.apache.org/licenses/LICENSE-2.0
984 :
985 : Unless required by applicable law or agreed to in writing, software
986 : distributed under the License is distributed on an "AS IS" BASIS,
987 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
988 : See the License for the specific language governing permissions and
989 : limitations under the License.
990 : */
|