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