Line data Source code
1 : /* File: consistency_lifeline.c; Copyright and License: see below */
2 :
3 : #include "consistency/consistency_lifeline.h"
4 : #include "ctrl_classifier_controller.h"
5 : #include "ctrl_diagram_controller.h"
6 : #include "set/data_full_id_list.h"
7 : #include "u8/u8_trace.h"
8 : #include "u8/u8_log.h"
9 :
10 42 : void consistency_lifeline_init( consistency_lifeline_t *this_,
11 : data_database_reader_t *db_reader,
12 : struct ctrl_classifier_controller_struct *clfy_ctrl,
13 : struct ctrl_diagram_controller_struct *diag_ctrl )
14 : {
15 42 : U8_TRACE_BEGIN();
16 42 : assert( NULL != db_reader );
17 42 : assert( NULL != clfy_ctrl );
18 42 : assert( NULL != diag_ctrl );
19 :
20 42 : (*this_).db_reader = db_reader;
21 42 : (*this_).clfy_ctrl = clfy_ctrl;
22 42 : (*this_).diag_ctrl = diag_ctrl;
23 42 : data_rules_init( &((*this_).rules) );
24 :
25 42 : U8_TRACE_END();
26 42 : }
27 :
28 42 : void consistency_lifeline_destroy( consistency_lifeline_t *this_ )
29 : {
30 42 : U8_TRACE_BEGIN();
31 :
32 42 : data_rules_destroy( &((*this_).rules) );
33 42 : (*this_).db_reader = NULL;
34 42 : (*this_).clfy_ctrl = NULL;
35 42 : (*this_).diag_ctrl = NULL;
36 :
37 42 : U8_TRACE_END();
38 42 : }
39 :
40 5 : u8_error_t consistency_lifeline_delete_lifelines ( consistency_lifeline_t *this_,
41 : const data_diagram_t *updated_diagram
42 : )
43 : {
44 5 : U8_TRACE_BEGIN();
45 5 : assert( NULL != updated_diagram );
46 5 : u8_error_t result = U8_ERROR_NONE;
47 :
48 5 : const data_diagram_type_t new_type = data_diagram_get_diagram_type ( updated_diagram );
49 5 : if ( ! data_rules_diagram_is_scenario( &((*this_).rules), new_type ) )
50 : {
51 : /* this diagram type must not have any lifelines */
52 : data_small_set_t lifelines_to_delete;
53 2 : data_small_set_init( &lifelines_to_delete );
54 :
55 : /* search all contained diagramelements */
56 2 : const data_row_id_t diagram_id = data_diagram_get_row_id ( updated_diagram );
57 2 : uint32_t diagramelement_count = 0;
58 4 : result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
59 : diagram_id,
60 : CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES,
61 2 : &((*this_).private_temp_diagele_buf),
62 : &diagramelement_count
63 : );
64 2 : if ( U8_ERROR_NONE == result )
65 : {
66 : /* search the diagramelements */
67 3 : for ( uint32_t index = 0; index < diagramelement_count; index ++ )
68 : {
69 1 : data_diagramelement_t *const current_diagele
70 : = &((*this_).private_temp_diagele_buf[index]);
71 1 : const data_id_t feat_to_delete = data_diagramelement_get_focused_feature_data_id( current_diagele );
72 1 : if ( data_id_is_valid( &feat_to_delete ) )
73 : {
74 : /* diagramelement with a focused feature found */
75 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */
76 1 : result |= data_small_set_add_obj( &lifelines_to_delete, feat_to_delete );
77 : }
78 : }
79 : }
80 : else
81 : {
82 0 : U8_LOG_ANOMALY( "consistency_lifeline_delete_lifelines could not load all diagram_elements of a diagram." );
83 : }
84 :
85 : /* delete all found lifelines */
86 : /* note that (*this_).private_temp_diagele_buf cannot be used here any longer due to re-entrancy by recursion */
87 2 : const uint32_t lifelines_count = data_small_set_get_count( &lifelines_to_delete );
88 3 : for ( uint32_t index2 = 0; index2 < lifelines_count; index2 ++ )
89 : {
90 1 : const data_id_t delete_feat = data_small_set_get_id( &lifelines_to_delete, index2 );
91 1 : assert( data_id_get_table( &delete_feat ) == DATA_TABLE_FEATURE );
92 1 : result |= ctrl_classifier_controller_delete_feature( (*this_).clfy_ctrl,
93 : data_id_get_row_id( &delete_feat ),
94 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
95 : );
96 : /* the current_diagele is already updated by another (recursive) consistency check. */
97 : }
98 :
99 2 : data_small_set_destroy( &lifelines_to_delete );
100 : }
101 :
102 5 : U8_TRACE_END_ERR( result );
103 5 : return result;
104 : }
105 :
106 5 : u8_error_t consistency_lifeline_create_lifelines( consistency_lifeline_t *this_,
107 : const data_diagram_t *updated_diagram )
108 : {
109 5 : U8_TRACE_BEGIN();
110 5 : assert( NULL != updated_diagram );
111 5 : u8_error_t result = U8_ERROR_NONE;
112 :
113 5 : const data_diagram_type_t new_type = data_diagram_get_diagram_type ( updated_diagram );
114 5 : if ( data_rules_diagram_is_scenario( &((*this_).rules), new_type ) )
115 : {
116 : /* this diagram type needs lifelines */
117 : data_full_id_t lifelines_to_create_buf[ CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES ];
118 : data_full_id_list_t lifelines_to_create;
119 3 : data_full_id_list_init( &lifelines_to_create,
120 : CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES,
121 : &lifelines_to_create_buf
122 : );
123 :
124 : /* search all contained diagramelements */
125 3 : const data_row_id_t diagram_id = data_diagram_get_row_id ( updated_diagram );
126 3 : uint32_t diagramelement_count = 0;
127 6 : result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
128 : diagram_id,
129 : CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES,
130 3 : &((*this_).private_temp_diagele_buf),
131 : &diagramelement_count
132 : );
133 :
134 3 : if ( U8_ERROR_NONE == result )
135 : {
136 : /* search the diagramelements */
137 6 : for ( uint32_t index = 0; index < diagramelement_count; index ++ )
138 : {
139 3 : data_diagramelement_t *const current_diagele
140 : = &((*this_).private_temp_diagele_buf[index]);
141 : const data_row_id_t focused_feature
142 3 : = data_diagramelement_get_focused_feature_row_id( current_diagele );
143 :
144 3 : if ( DATA_ROW_ID_VOID == focused_feature )
145 : {
146 : /* diagramelement without focused feature found */
147 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */
148 : const data_full_id_t diagramelement_ids = {
149 2 : .primary_id = data_diagramelement_get_data_id( current_diagele ),
150 2 : .secondary_id = data_diagramelement_get_classifier_data_id( current_diagele )
151 : };
152 2 : result |= data_full_id_list_add( &lifelines_to_create, &diagramelement_ids );
153 : }
154 : }
155 : }
156 : else
157 : {
158 0 : U8_LOG_ANOMALY( "consistency_lifeline_create_lifelines could not load all diagram_elements of a diagram." );
159 : }
160 :
161 : /* create all missing lifelines */
162 : /* note that (*this_).private_temp_diagele_buf cannot be used here any longer due to re-entrancy by recursion */
163 3 : const uint32_t lifelines_count = data_full_id_list_get_length( &lifelines_to_create );
164 5 : for ( uint32_t index2 = 0; index2 < lifelines_count; index2 ++ )
165 : {
166 2 : const data_full_id_t *const diagramelement_ids = data_full_id_list_get_const( &lifelines_to_create, index2 );
167 2 : result |= consistency_lifeline_private_create_one_lifeline ( this_, diagramelement_ids );
168 : }
169 :
170 3 : data_full_id_list_destroy( &lifelines_to_create );
171 : }
172 :
173 5 : U8_TRACE_END_ERR( result );
174 5 : return result;
175 : }
176 :
177 32 : u8_error_t consistency_lifeline_create_a_lifeline( consistency_lifeline_t *this_,
178 : const data_diagramelement_t *new_diagramelement )
179 : {
180 32 : U8_TRACE_BEGIN();
181 32 : assert( NULL != new_diagramelement );
182 32 : u8_error_t result = U8_ERROR_NONE;
183 :
184 : /* load the diagram and check the type */
185 : data_diagram_t the_diag;
186 32 : result |= data_database_reader_get_diagram_by_id( (*this_).db_reader,
187 : data_diagramelement_get_diagram_row_id( new_diagramelement ),
188 : &the_diag
189 : );
190 :
191 32 : if ( U8_ERROR_NONE == result )
192 : {
193 32 : const data_diagram_type_t dig_type = data_diagram_get_diagram_type( &the_diag );
194 32 : if ( data_rules_diagram_is_scenario( &((*this_).rules), dig_type ) )
195 : {
196 : const data_full_id_t diagramelement_ids = {
197 16 : .primary_id = data_diagramelement_get_data_id( new_diagramelement ),
198 16 : .secondary_id = data_diagramelement_get_classifier_data_id( new_diagramelement )
199 : };
200 16 : result |= consistency_lifeline_private_create_one_lifeline ( this_, &diagramelement_ids );
201 : }
202 : }
203 :
204 32 : U8_TRACE_END_ERR( result );
205 32 : return result;
206 : }
207 :
208 18 : u8_error_t consistency_lifeline_private_create_one_lifeline( consistency_lifeline_t *this_,
209 : const data_full_id_t *diagramelement_ids )
210 : {
211 18 : U8_TRACE_BEGIN();
212 18 : assert( NULL != diagramelement_ids );
213 18 : u8_error_t result = U8_ERROR_NONE;
214 18 : const data_id_t diagramelement_id = data_full_id_get_primary_id( diagramelement_ids );
215 18 : assert( DATA_TABLE_DIAGRAMELEMENT == data_id_get_table( &diagramelement_id ) );
216 18 : const data_id_t classifier_id = data_full_id_get_secondary_id( diagramelement_ids );
217 18 : assert( DATA_TABLE_CLASSIFIER == data_id_get_table( &classifier_id ) );
218 :
219 : /* define the lifeline to create */
220 : data_feature_t new_lifeline;
221 18 : result |= data_feature_init_new( &new_lifeline,
222 : DATA_FEATURE_TYPE_LIFELINE,
223 : data_id_get_row_id( &classifier_id ),
224 : "", /* key */
225 : "", /* value or type */
226 : "", /* description */
227 : 0 /* list_order */
228 : );
229 :
230 : /* create the lifeline */
231 18 : data_row_id_t new_feature_id = DATA_ROW_ID_VOID;
232 18 : result |= ctrl_classifier_controller_create_feature( (*this_).clfy_ctrl,
233 : &new_lifeline,
234 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
235 : &new_feature_id
236 : );
237 :
238 : /* the newly created lifeline is the focused feature */
239 18 : result |= ctrl_diagram_controller_update_diagramelement_focused_feature_id( (*this_).diag_ctrl,
240 : data_id_get_row_id( &diagramelement_id ),
241 : new_feature_id,
242 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
243 : );
244 :
245 : /* cleanup */
246 18 : data_feature_destroy ( &new_lifeline );
247 :
248 18 : U8_TRACE_END_ERR( result );
249 18 : return result;
250 : }
251 :
252 5 : u8_error_t consistency_lifeline_delete_a_lifeline( consistency_lifeline_t *this_,
253 : const data_diagramelement_t *deleted_diagramelement )
254 : {
255 5 : U8_TRACE_BEGIN();
256 5 : assert( NULL != deleted_diagramelement );
257 5 : u8_error_t result = U8_ERROR_NONE;
258 :
259 : /* delete the lifeline of the already deleted data_diagramelement_t */
260 : const data_row_id_t focused_feature_id
261 5 : = data_diagramelement_get_focused_feature_row_id( deleted_diagramelement );
262 5 : if ( DATA_ROW_ID_VOID != focused_feature_id )
263 : {
264 4 : result |= ctrl_classifier_controller_delete_feature( (*this_).clfy_ctrl,
265 : focused_feature_id,
266 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
267 : );
268 : }
269 :
270 5 : U8_TRACE_END_ERR( result );
271 5 : return result;
272 : }
273 :
274 9 : u8_error_t consistency_lifeline_unlink_lifeline( consistency_lifeline_t *this_,
275 : const data_feature_t *deleted_feature )
276 : {
277 9 : U8_TRACE_BEGIN();
278 9 : assert( NULL != deleted_feature );
279 9 : u8_error_t result = U8_ERROR_NONE;
280 :
281 9 : if ( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type ( deleted_feature ) )
282 : {
283 6 : const data_row_id_t classifier_id = data_feature_get_classifier_row_id ( deleted_feature );
284 6 : const data_row_id_t deleted_feature_id = data_feature_get_row_id( deleted_feature );
285 : data_small_set_t diag_ele_to_unlink;
286 6 : data_small_set_init( &diag_ele_to_unlink );
287 :
288 : /* search all diagramelements of the classifier */
289 : uint32_t diagramelement_count;
290 12 : result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
291 : classifier_id,
292 : CONSISTENCY_LIFELINE_CONST_MAX_TEMP_DIAGELES,
293 6 : &((*this_).private_temp_diagele_buf),
294 : &diagramelement_count
295 : );
296 :
297 6 : if ( U8_ERROR_NONE == result )
298 : {
299 : /* search the diagramelements */
300 12 : for ( uint32_t index = 0; index < diagramelement_count; index ++ )
301 : {
302 6 : data_diagramelement_t *const current_diagele
303 : = &((*this_).private_temp_diagele_buf[index]);
304 : const data_row_id_t focused_feature
305 6 : = data_diagramelement_get_focused_feature_row_id( current_diagele );
306 :
307 6 : if ( focused_feature == deleted_feature_id )
308 : {
309 : /* diagramelement with the just deleted focused feature found */
310 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */
311 2 : const data_id_t diagele_id = data_diagramelement_get_data_id( current_diagele );
312 2 : result |= data_small_set_add_obj( &diag_ele_to_unlink, diagele_id );
313 : }
314 : }
315 : }
316 : else
317 : {
318 0 : U8_LOG_ANOMALY( "consistency_lifeline_unlink_lifeline could not load all lifelines of a classifier." );
319 : }
320 :
321 : /* unlink all found diagram elements (there should be exactly one) */
322 : /* note that (*this_).private_temp_diagele_buf cannot be used here any longer due to re-entrancy by recursion */
323 6 : const uint32_t diag_ele_count = data_small_set_get_count( &diag_ele_to_unlink );
324 6 : if ( diag_ele_count != 1 )
325 : {
326 4 : U8_LOG_ANOMALY_INT( "Unlinking a just deleted lifeline that had not exactly one occurrence:",
327 : diag_ele_count
328 : );
329 : }
330 8 : for ( uint32_t index2 = 0; index2 < diag_ele_count; index2 ++ )
331 : {
332 2 : const data_id_t diagele_to_unlink = data_small_set_get_id( &diag_ele_to_unlink, index2 );
333 2 : assert( data_id_get_table( &diagele_to_unlink ) == DATA_TABLE_DIAGRAMELEMENT );
334 2 : result |= ctrl_diagram_controller_update_diagramelement_focused_feature_id( (*this_).diag_ctrl,
335 : data_id_get_row_id( &diagele_to_unlink ),
336 : DATA_ROW_ID_VOID,
337 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
338 : );
339 : }
340 :
341 6 : data_small_set_destroy( &diag_ele_to_unlink );
342 : }
343 :
344 9 : U8_TRACE_END_ERR( result );
345 9 : return result;
346 : }
347 :
348 :
349 : /*
350 : Copyright 2018-2024 Andreas Warnke
351 :
352 : Licensed under the Apache License, Version 2.0 (the "License");
353 : you may not use this file except in compliance with the License.
354 : You may obtain a copy of the License at
355 :
356 : http://www.apache.org/licenses/LICENSE-2.0
357 :
358 : Unless required by applicable law or agreed to in writing, software
359 : distributed under the License is distributed on an "AS IS" BASIS,
360 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
361 : See the License for the specific language governing permissions and
362 : limitations under the License.
363 : */
|