Line data Source code
1 : /* File: ctrl_consistency_checker.c; Copyright and License: see below */
2 :
3 : #include "ctrl_consistency_checker.h"
4 : #include "storage/data_database_consistency_checker.h"
5 : #include "entity/data_id.h"
6 : #include "u8/u8_trace.h"
7 : #include "u8/u8_log.h"
8 : #include <assert.h>
9 :
10 84 : void ctrl_consistency_checker_init ( ctrl_consistency_checker_t *this_,
11 : data_database_t *database,
12 : data_database_reader_t *db_reader,
13 : data_database_writer_t *db_writer )
14 : {
15 84 : U8_TRACE_BEGIN();
16 84 : assert( NULL != database );
17 84 : assert( NULL != db_reader );
18 84 : assert( NULL != db_writer );
19 :
20 84 : (*this_).database = database;
21 84 : (*this_).db_reader = db_reader;
22 84 : (*this_).db_writer = db_writer;
23 :
24 84 : data_database_consistency_checker_init( &((*this_).db_checker), database );
25 :
26 84 : U8_TRACE_END();
27 84 : }
28 :
29 84 : void ctrl_consistency_checker_destroy ( ctrl_consistency_checker_t *this_ )
30 : {
31 84 : U8_TRACE_BEGIN();
32 :
33 84 : data_database_consistency_checker_destroy( &((*this_).db_checker) );
34 :
35 84 : (*this_).database = NULL;
36 84 : (*this_).db_reader = NULL;
37 84 : (*this_).db_writer = NULL;
38 :
39 84 : U8_TRACE_END();
40 84 : }
41 :
42 30 : u8_error_t ctrl_consistency_checker_repair_database ( ctrl_consistency_checker_t *this_,
43 : bool modify_db,
44 : uint32_t *out_err,
45 : uint32_t *out_fix,
46 : utf8stream_writer_t *out_english_report )
47 : {
48 30 : U8_TRACE_BEGIN();
49 30 : assert ( NULL != out_english_report );
50 30 : u8_error_t err_result = U8_ERROR_NONE;
51 30 : uint32_t error_count = 0;
52 30 : uint32_t fix_count = 0;
53 :
54 : /* write report title */
55 30 : if ( modify_db )
56 : {
57 10 : utf8stream_writer_write_str( out_english_report, "TITLE: Repair database\n" );
58 : }
59 : else
60 : {
61 20 : utf8stream_writer_write_str( out_english_report, "TITLE: Check database\n" );
62 : }
63 :
64 : /* == find inconsistencies in drawings == */
65 :
66 : /* get all root diagrams */
67 30 : err_result |= ctrl_consistency_checker_private_ensure_single_root_diagram( this_, modify_db, &error_count, &fix_count, out_english_report );
68 :
69 : /* find invalid and circular diagram parent links */
70 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_diagram_parents( this_, modify_db, &error_count, &fix_count, out_english_report );
71 :
72 : /* find nonreferencing diagramelements */
73 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_diagramelements( this_, modify_db, &error_count, &fix_count, out_english_report );
74 :
75 : /* find illreferencing diagramelements */
76 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_diagele_features( this_, modify_db, &error_count, &fix_count, out_english_report );
77 :
78 : /* find unreferenced, invisible classifiers */
79 30 : err_result |= ctrl_consistency_checker_private_ensure_referenced_classifiers( this_, modify_db, &error_count, &fix_count, out_english_report );
80 :
81 : /* == find inconsistencies in meta model == */
82 :
83 : /* find nonreferencing features */
84 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_feature_parents( this_, modify_db, &error_count, &fix_count, out_english_report );
85 :
86 : /* find nonreferencing relationships */
87 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_relationship_classifiers( this_, modify_db, &error_count, &fix_count, out_english_report );
88 :
89 : /* find illreferencing relationships */
90 30 : err_result |= ctrl_consistency_checker_private_ensure_valid_relationship_features( this_, modify_db, &error_count, &fix_count, out_english_report );
91 :
92 : /* prepare results and return */
93 30 : if ( NULL != out_err )
94 : {
95 30 : (*out_err) = error_count;
96 : }
97 30 : if ( NULL != out_fix )
98 : {
99 30 : (*out_fix) = fix_count;
100 : }
101 :
102 : /* write report summary */
103 30 : const char *db_filename = data_database_get_filename_ptr ( (*this_).database );
104 30 : utf8stream_writer_write_str( out_english_report, "SUMMARY: " );
105 30 : if ( db_filename != NULL )
106 : {
107 30 : utf8stream_writer_write_str( out_english_report, "\n File: " );
108 30 : utf8stream_writer_write_str( out_english_report, db_filename );
109 : }
110 30 : utf8stream_writer_write_str( out_english_report, "\n Errors found: " );
111 30 : utf8stream_writer_write_int( out_english_report, error_count );
112 30 : utf8stream_writer_write_str( out_english_report, "\n Errors fixed: " );
113 30 : utf8stream_writer_write_int( out_english_report, fix_count );
114 30 : utf8stream_writer_write_str( out_english_report, "\n" );
115 :
116 : /* if not all errors fixed, set result to U8_ERROR_DB_STRUCTURE */
117 30 : if ( error_count > fix_count )
118 : {
119 10 : err_result |= U8_ERROR_DB_STRUCTURE;
120 : }
121 :
122 30 : U8_TRACE_END_ERR( err_result );
123 30 : return err_result;
124 : }
125 :
126 30 : u8_error_t ctrl_consistency_checker_private_ensure_single_root_diagram ( ctrl_consistency_checker_t *this_,
127 : bool modify_db,
128 : uint32_t *io_err,
129 : uint32_t *io_fix,
130 : utf8stream_writer_t *out_english_report )
131 : {
132 30 : U8_TRACE_BEGIN();
133 30 : assert ( NULL != io_err );
134 30 : assert ( NULL != io_fix );
135 30 : assert ( NULL != out_english_report );
136 30 : u8_error_t result = U8_ERROR_NONE;
137 :
138 : /* write report title */
139 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure a single root diagram\n" );
140 :
141 : /* get all root diagrams */
142 : data_small_set_t all_roots;
143 30 : data_small_set_init( &all_roots );
144 : data_diagram_iterator_t diagram_iterator;
145 30 : result |= data_diagram_iterator_init_empty( &diagram_iterator );
146 :
147 30 : result |= data_database_reader_get_diagrams_by_parent_id( (*this_).db_reader,
148 : DATA_ROW_VOID,
149 : &diagram_iterator
150 : );
151 :
152 30 : if ( U8_ERROR_NONE != result )
153 : {
154 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
155 : }
156 :
157 62 : while ( data_diagram_iterator_has_next( &diagram_iterator ) )
158 : {
159 32 : result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram) );
160 32 : result |= data_small_set_add_obj( &all_roots, data_diagram_get_data_id( &((*this_).temp_diagram) ) );
161 :
162 32 : utf8stream_writer_write_str( out_english_report, " INFO: Root diagram: " );
163 32 : utf8stream_writer_write_int( out_english_report, data_diagram_get_row_id( &((*this_).temp_diagram) ) );
164 32 : utf8stream_writer_write_str( out_english_report, ": " );
165 32 : utf8stream_writer_write_str( out_english_report, data_diagram_get_name_const( &((*this_).temp_diagram) ) );
166 32 : utf8stream_writer_write_str( out_english_report, "\n" );
167 : }
168 30 : const uint_fast32_t root_diagram_count = data_small_set_get_count( &all_roots );
169 30 : utf8stream_writer_write_str( out_english_report, " ROOT DIAGRAM COUNT: " );
170 30 : utf8stream_writer_write_int( out_english_report, root_diagram_count );
171 30 : utf8stream_writer_write_str( out_english_report, "\n" );
172 30 : result |= data_diagram_iterator_destroy( &diagram_iterator );
173 :
174 30 : if ( root_diagram_count == 0 )
175 : {
176 0 : (*io_err) ++;
177 0 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Create a diagram via the GUI.\n" );
178 : }
179 30 : else if ( root_diagram_count > 1 )
180 : {
181 2 : (*io_err) += (root_diagram_count-1) ;
182 2 : const data_id_t proposed_root_diagram = data_small_set_get_id( &all_roots, 0 );
183 2 : const data_row_t proposed_root_diagram_id = data_id_get_row_id( &proposed_root_diagram );
184 2 : if ( ! modify_db )
185 : {
186 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Attach additional root diagrams below the first: " );
187 1 : utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id );
188 1 : utf8stream_writer_write_str( out_english_report, "\n" );
189 : }
190 : else
191 : {
192 2 : for ( int list_pos = 1; list_pos < root_diagram_count; list_pos ++ )
193 : {
194 1 : const data_id_t proposed_child_diagram = data_small_set_get_id( &all_roots, list_pos );
195 1 : const data_row_t proposed_child_diagram_id = data_id_get_row_id( &proposed_child_diagram );
196 : const u8_error_t data_err
197 1 : = data_database_writer_update_diagram_parent_id( (*this_).db_writer,
198 : proposed_child_diagram_id,
199 : proposed_root_diagram_id,
200 : NULL
201 : );
202 1 : if ( U8_ERROR_NONE == data_err )
203 : {
204 1 : utf8stream_writer_write_str( out_english_report, " FIX: Diagram " );
205 1 : utf8stream_writer_write_int( out_english_report, proposed_child_diagram_id );
206 1 : utf8stream_writer_write_str( out_english_report, " attached to " );
207 1 : utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id);
208 1 : utf8stream_writer_write_str( out_english_report, "\n" );
209 1 : (*io_fix) ++;
210 : }
211 : else
212 : {
213 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
214 0 : result |= data_err;
215 : }
216 : }
217 : }
218 : }
219 30 : data_small_set_destroy( &all_roots );
220 :
221 30 : U8_TRACE_END_ERR( result );
222 30 : return result;
223 : }
224 :
225 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagram_parents ( ctrl_consistency_checker_t *this_,
226 : bool modify_db,
227 : uint32_t *io_err,
228 : uint32_t *io_fix,
229 : utf8stream_writer_t *out_english_report )
230 : {
231 30 : U8_TRACE_BEGIN();
232 30 : assert ( NULL != io_err );
233 30 : assert ( NULL != out_english_report );
234 30 : u8_error_t err_result = U8_ERROR_NONE;
235 : u8_error_t data_err;
236 :
237 : /* write report title */
238 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that no circular/invalid references of diagram parents exist\n" );
239 :
240 : data_small_set_t circ_ref;
241 30 : data_small_set_init( &circ_ref );
242 30 : data_err = data_database_consistency_checker_find_circular_diagram_parents ( &((*this_).db_checker), &circ_ref );
243 30 : if ( U8_ERROR_NONE == data_err )
244 : {
245 30 : uint32_t circ_ref_count = data_small_set_get_count( &circ_ref );
246 :
247 30 : utf8stream_writer_write_str( out_english_report, " DIAGRAMS WITH CIRCLUAR OR INVALID PARENT REFERENCES: " );
248 30 : utf8stream_writer_write_int( out_english_report, circ_ref_count );
249 30 : utf8stream_writer_write_str( out_english_report, "\n" );
250 :
251 30 : if ( circ_ref_count != 0 )
252 : {
253 4 : (*io_err) += circ_ref_count;
254 :
255 : /* get the root diagram */
256 4 : data_row_t root_diag_id = DATA_ROW_VOID;
257 : {
258 : data_diagram_iterator_t diagram_iterator;
259 4 : err_result |= data_diagram_iterator_init_empty( &diagram_iterator );
260 4 : err_result |= data_database_reader_get_diagrams_by_parent_id( (*this_).db_reader,
261 : DATA_ROW_VOID,
262 : &diagram_iterator
263 : );
264 4 : if (( U8_ERROR_NONE == err_result )&& data_diagram_iterator_has_next( &diagram_iterator ) )
265 : {
266 4 : err_result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram) );
267 4 : root_diag_id = data_diagram_get_row_id( &((*this_).temp_diagram) );
268 : }
269 4 : err_result |= data_diagram_iterator_destroy( &diagram_iterator );
270 : }
271 :
272 4 : if ( ! modify_db )
273 : {
274 2 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Move " );
275 2 : utf8stream_writer_write_int( out_english_report, circ_ref_count );
276 2 : utf8stream_writer_write_str( out_english_report, " diagrams below root diagram " );
277 2 : utf8stream_writer_write_int( out_english_report, root_diag_id );
278 2 : utf8stream_writer_write_str( out_english_report, ".\n" );
279 : }
280 : else
281 : {
282 6 : for ( int list_pos = 0; list_pos < circ_ref_count; list_pos ++ )
283 : {
284 4 : data_id_t diagram_id = data_small_set_get_id( &circ_ref, list_pos );
285 4 : data_row_t diagram_row_id = data_id_get_row_id( &diagram_id );
286 :
287 4 : data_err = data_database_writer_update_diagram_parent_id ( (*this_).db_writer,
288 : diagram_row_id,
289 : root_diag_id,
290 : NULL /*out_old_diagram*/
291 : );
292 4 : if ( U8_ERROR_NONE == data_err )
293 : {
294 4 : utf8stream_writer_write_str( out_english_report, " FIX: Diagram " );
295 4 : utf8stream_writer_write_int( out_english_report, diagram_row_id );
296 4 : utf8stream_writer_write_str( out_english_report, " moved below root diagram " );
297 4 : utf8stream_writer_write_int( out_english_report, root_diag_id );
298 4 : utf8stream_writer_write_str( out_english_report, ".\n" );
299 4 : (*io_fix) ++;
300 : }
301 : else
302 : {
303 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
304 0 : err_result |= data_err;
305 : }
306 : }
307 : }
308 : }
309 : }
310 : else
311 : {
312 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
313 0 : err_result |= data_err;
314 : }
315 30 : data_small_set_destroy( &circ_ref );
316 :
317 30 : U8_TRACE_END_ERR( err_result );
318 30 : return err_result;
319 : }
320 :
321 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagramelements ( ctrl_consistency_checker_t *this_,
322 : bool modify_db,
323 : uint32_t *io_err,
324 : uint32_t *io_fix,
325 : utf8stream_writer_t *out_english_report )
326 : {
327 30 : U8_TRACE_BEGIN();
328 30 : assert ( NULL != io_err );
329 30 : assert ( NULL != io_fix );
330 30 : assert ( NULL != out_english_report );
331 30 : u8_error_t err_result = U8_ERROR_NONE;
332 : u8_error_t data_err;
333 :
334 : /* write report title */
335 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference valid diagrams and classifiers\n" );
336 :
337 : data_small_set_t unref;
338 30 : data_small_set_init( &unref );
339 30 : data_err = data_database_consistency_checker_find_nonreferencing_diagramelements ( &((*this_).db_checker), &unref );
340 30 : if ( U8_ERROR_NONE == data_err )
341 : {
342 30 : uint32_t unref_count = data_small_set_get_count( &unref );
343 :
344 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING DIAGRAMELEMENTS COUNT: " );
345 30 : utf8stream_writer_write_int( out_english_report, unref_count );
346 30 : utf8stream_writer_write_str( out_english_report, "\n" );
347 :
348 30 : if ( unref_count != 0 )
349 : {
350 2 : (*io_err) += unref_count;
351 :
352 2 : if ( ! modify_db )
353 : {
354 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
355 1 : utf8stream_writer_write_int( out_english_report, unref_count );
356 1 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
357 : }
358 : else
359 : {
360 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
361 : {
362 3 : data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
363 3 : data_row_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
364 3 : data_err = data_database_writer_delete_diagramelement ( (*this_).db_writer, diagramelement_row_id, NULL );
365 3 : if ( U8_ERROR_NONE == data_err )
366 : {
367 3 : utf8stream_writer_write_str( out_english_report, " FIX: Diagramelement " );
368 3 : utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
369 3 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
370 3 : (*io_fix) ++;
371 : }
372 : else
373 : {
374 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
375 0 : err_result |= data_err;
376 : }
377 : }
378 : }
379 : }
380 : }
381 : else
382 : {
383 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
384 0 : err_result |= data_err;
385 : }
386 :
387 30 : U8_TRACE_END_ERR( err_result );
388 30 : return err_result;
389 : }
390 :
391 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagele_features ( ctrl_consistency_checker_t *this_,
392 : bool modify_db,
393 : uint32_t *io_err,
394 : uint32_t *io_fix,
395 : utf8stream_writer_t *out_english_report )
396 : {
397 30 : U8_TRACE_BEGIN();
398 30 : assert ( NULL != io_err );
399 30 : assert ( NULL != io_fix );
400 30 : assert ( NULL != out_english_report );
401 30 : u8_error_t err_result = U8_ERROR_NONE;
402 : u8_error_t data_err;
403 :
404 : /* write report title */
405 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference NULL or valid features\n" );
406 :
407 : data_small_set_t unref;
408 30 : data_small_set_init( &unref );
409 30 : data_err = data_database_consistency_checker_find_invalid_focused_features ( &((*this_).db_checker), &unref );
410 30 : if ( U8_ERROR_NONE == data_err )
411 : {
412 30 : uint32_t unref_count = data_small_set_get_count( &unref );
413 :
414 30 : utf8stream_writer_write_str( out_english_report, " ILLREFERENCING DIAGRAMELEMENTS COUNT: " );
415 30 : utf8stream_writer_write_int( out_english_report, unref_count );
416 30 : utf8stream_writer_write_str( out_english_report, "\n" );
417 :
418 30 : if ( unref_count != 0 )
419 : {
420 2 : (*io_err) += unref_count;
421 :
422 2 : if ( ! modify_db )
423 : {
424 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Unlink focused features from " );
425 1 : utf8stream_writer_write_int( out_english_report, unref_count );
426 1 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
427 : }
428 : else
429 : {
430 3 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
431 : {
432 2 : data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
433 2 : data_row_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
434 2 : data_err = data_database_writer_update_diagramelement_focused_feature_id ( (*this_).db_writer, diagramelement_row_id, DATA_ROW_VOID, NULL );
435 2 : if ( U8_ERROR_NONE == data_err )
436 : {
437 2 : utf8stream_writer_write_str( out_english_report, " FIX: Focused features unlinked from " );
438 2 : utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
439 2 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
440 2 : (*io_fix) ++;
441 : }
442 : else
443 : {
444 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
445 0 : err_result |= data_err;
446 : }
447 : }
448 : }
449 : }
450 : }
451 : else
452 : {
453 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
454 0 : err_result |= data_err;
455 : }
456 :
457 30 : U8_TRACE_END_ERR( err_result );
458 30 : return err_result;
459 : }
460 :
461 30 : u8_error_t ctrl_consistency_checker_private_ensure_referenced_classifiers ( ctrl_consistency_checker_t *this_,
462 : bool modify_db,
463 : uint32_t *io_err,
464 : uint32_t *io_fix,
465 : utf8stream_writer_t *out_english_report )
466 : {
467 30 : U8_TRACE_BEGIN();
468 30 : assert ( NULL != io_err );
469 30 : assert ( NULL != io_fix );
470 30 : assert ( NULL != out_english_report );
471 30 : u8_error_t err_result = U8_ERROR_NONE;
472 : u8_error_t data_err;
473 :
474 : /* write report title */
475 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that classifiers are referenced\n" );
476 :
477 : data_small_set_t unref;
478 30 : data_small_set_init( &unref );
479 30 : data_err = data_database_consistency_checker_find_unreferenced_classifiers ( &((*this_).db_checker), &unref );
480 30 : if ( U8_ERROR_NONE == data_err )
481 : {
482 30 : uint32_t unref_count = data_small_set_get_count( &unref );
483 :
484 30 : utf8stream_writer_write_str( out_english_report, " UNREFERENCED CLASSIFIER COUNT: " );
485 30 : utf8stream_writer_write_int( out_english_report, unref_count );
486 30 : utf8stream_writer_write_str( out_english_report, "\n" );
487 :
488 30 : if ( unref_count != 0 )
489 : {
490 4 : (*io_err) += unref_count;
491 :
492 4 : if ( ! modify_db )
493 : {
494 2 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
495 2 : utf8stream_writer_write_int( out_english_report, unref_count );
496 2 : utf8stream_writer_write_str( out_english_report, " classifiers.\n" );
497 : }
498 : else
499 : {
500 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
501 : {
502 2 : data_id_t classifier_id = data_small_set_get_id( &unref, list_pos );
503 2 : data_row_t classifier_row_id = data_id_get_row_id( &classifier_id );
504 2 : err_result |= data_database_consistency_checker_kill_classifier ( &((*this_).db_checker), classifier_row_id );
505 2 : if ( U8_ERROR_NONE == err_result )
506 : {
507 2 : utf8stream_writer_write_str( out_english_report, " FIX: Classifier " );
508 2 : utf8stream_writer_write_int( out_english_report, classifier_row_id );
509 2 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
510 2 : (*io_fix) ++;
511 : }
512 : else
513 : {
514 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
515 : }
516 : }
517 : }
518 : }
519 : }
520 : else
521 : {
522 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
523 0 : err_result |= data_err;
524 : }
525 :
526 30 : U8_TRACE_END_ERR( err_result );
527 30 : return err_result;
528 : }
529 :
530 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_feature_parents ( ctrl_consistency_checker_t *this_,
531 : bool modify_db,
532 : uint32_t *io_err,
533 : uint32_t *io_fix,
534 : utf8stream_writer_t *out_english_report )
535 : {
536 30 : U8_TRACE_BEGIN();
537 30 : assert ( NULL != io_err );
538 30 : assert ( NULL != io_fix );
539 30 : assert ( NULL != out_english_report );
540 30 : u8_error_t err_result = U8_ERROR_NONE;
541 : u8_error_t data_err;
542 :
543 : /* write report title */
544 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that features have valid classifiers\n" );
545 :
546 : data_small_set_t unref;
547 30 : data_small_set_init( &unref );
548 30 : data_err = data_database_consistency_checker_find_unreferenced_features ( &((*this_).db_checker), &unref );
549 30 : if ( U8_ERROR_NONE == data_err )
550 : {
551 30 : uint32_t unref_count = data_small_set_get_count( &unref );
552 :
553 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING FEATURES COUNT: " );
554 30 : utf8stream_writer_write_int( out_english_report, unref_count );
555 30 : utf8stream_writer_write_str( out_english_report, "\n" );
556 :
557 30 : if ( unref_count != 0 )
558 : {
559 3 : (*io_err) += unref_count;
560 :
561 3 : if ( ! modify_db )
562 : {
563 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
564 1 : utf8stream_writer_write_int( out_english_report, unref_count );
565 1 : utf8stream_writer_write_str( out_english_report, " features.\n" );
566 : }
567 : else
568 : {
569 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
570 : {
571 2 : data_id_t feature_id = data_small_set_get_id( &unref, list_pos );
572 2 : data_row_t feature_row_id = data_id_get_row_id( &feature_id );
573 2 : data_err = data_database_writer_delete_feature ( (*this_).db_writer, feature_row_id, NULL );
574 2 : if ( U8_ERROR_NONE == data_err )
575 : {
576 2 : utf8stream_writer_write_str( out_english_report, " FIX: Feature " );
577 2 : utf8stream_writer_write_int( out_english_report, feature_row_id );
578 2 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
579 2 : (*io_fix) ++;
580 : }
581 : else
582 : {
583 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
584 0 : err_result |= data_err;
585 : }
586 : }
587 : }
588 : }
589 : }
590 : else
591 : {
592 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
593 0 : err_result |= data_err;
594 : }
595 :
596 30 : U8_TRACE_END_ERR( err_result );
597 30 : return err_result;
598 : }
599 :
600 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_classifiers ( ctrl_consistency_checker_t *this_,
601 : bool modify_db,
602 : uint32_t *io_err,
603 : uint32_t *io_fix,
604 : utf8stream_writer_t *out_english_report )
605 : {
606 30 : U8_TRACE_BEGIN();
607 30 : assert ( NULL != io_err );
608 30 : assert ( NULL != io_fix );
609 30 : assert ( NULL != out_english_report );
610 30 : u8_error_t err_result = U8_ERROR_NONE;
611 : u8_error_t data_err;
612 :
613 : /* write report title */
614 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link valid classifiers\n" );
615 :
616 : data_small_set_t unref;
617 30 : data_small_set_init( &unref );
618 30 : data_err = data_database_consistency_checker_find_unreferenced_relationships ( &((*this_).db_checker), &unref );
619 30 : if ( U8_ERROR_NONE == data_err )
620 : {
621 30 : uint32_t unref_count = data_small_set_get_count( &unref );
622 :
623 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING RELATIONSHIPS COUNT: " );
624 30 : utf8stream_writer_write_int( out_english_report, unref_count );
625 30 : utf8stream_writer_write_str( out_english_report, "\n" );
626 :
627 30 : if ( unref_count != 0 )
628 : {
629 3 : (*io_err) += unref_count;
630 :
631 3 : if ( ! modify_db )
632 : {
633 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
634 1 : utf8stream_writer_write_int( out_english_report, unref_count );
635 1 : utf8stream_writer_write_str( out_english_report, " relationships.\n" );
636 : }
637 : else
638 : {
639 6 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
640 : {
641 4 : data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
642 4 : data_row_t relation_row_id = data_id_get_row_id( &relationship_id );
643 4 : data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
644 4 : if ( U8_ERROR_NONE == data_err )
645 : {
646 4 : utf8stream_writer_write_str( out_english_report, " FIX: Relationship " );
647 4 : utf8stream_writer_write_int( out_english_report, relation_row_id );
648 4 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
649 4 : (*io_fix) ++;
650 : }
651 : else
652 : {
653 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
654 0 : err_result |= data_err;
655 : }
656 : }
657 : }
658 : }
659 : }
660 : else
661 : {
662 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
663 0 : err_result |= data_err;
664 : }
665 :
666 30 : U8_TRACE_END_ERR( err_result );
667 30 : return err_result;
668 : }
669 :
670 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_features ( ctrl_consistency_checker_t *this_,
671 : bool modify_db,
672 : uint32_t *io_err,
673 : uint32_t *io_fix,
674 : utf8stream_writer_t *out_english_report )
675 : {
676 30 : U8_TRACE_BEGIN();
677 30 : assert ( NULL != io_err );
678 30 : assert ( NULL != io_fix );
679 30 : assert ( NULL != out_english_report );
680 30 : u8_error_t err_result = U8_ERROR_NONE;
681 : u8_error_t data_err;
682 :
683 : /* write report title */
684 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link NULL or valid features\n" );
685 :
686 : data_small_set_t unref;
687 30 : data_small_set_init( &unref );
688 30 : data_err = data_database_consistency_checker_find_invalid_relationship_features ( &((*this_).db_checker), &unref );
689 30 : if ( U8_ERROR_NONE == data_err )
690 : {
691 30 : uint32_t unref_count = data_small_set_get_count( &unref );
692 :
693 30 : utf8stream_writer_write_str( out_english_report, " ILLREFERENCING RELATIONSHIPS COUNT: " );
694 30 : utf8stream_writer_write_int( out_english_report, unref_count );
695 30 : utf8stream_writer_write_str( out_english_report, "\n" );
696 :
697 30 : if ( unref_count != 0 )
698 : {
699 2 : (*io_err) += unref_count;
700 :
701 2 : if ( ! modify_db )
702 : {
703 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
704 1 : utf8stream_writer_write_int( out_english_report, unref_count );
705 1 : utf8stream_writer_write_str( out_english_report, " relationships.\n" );
706 : }
707 : else
708 : {
709 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
710 : {
711 3 : data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
712 3 : data_row_t relation_row_id = data_id_get_row_id( &relationship_id );
713 3 : data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
714 3 : if ( U8_ERROR_NONE == data_err )
715 : {
716 3 : utf8stream_writer_write_str( out_english_report, " FIX: Relationship " );
717 3 : utf8stream_writer_write_int( out_english_report, relation_row_id );
718 3 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
719 3 : (*io_fix) ++;
720 : }
721 : else
722 : {
723 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
724 0 : err_result |= data_err;
725 : }
726 : }
727 : }
728 : }
729 : }
730 : else
731 : {
732 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
733 0 : err_result |= data_err;
734 : }
735 :
736 30 : U8_TRACE_END_ERR( err_result );
737 30 : return err_result;
738 : }
739 :
740 :
741 : /*
742 : Copyright 2016-2024 Andreas Warnke
743 :
744 : Licensed under the Apache License, Version 2.0 (the "License");
745 : you may not use this file except in compliance with the License.
746 : You may obtain a copy of the License at
747 :
748 : http://www.apache.org/licenses/LICENSE-2.0
749 :
750 : Unless required by applicable law or agreed to in writing, software
751 : distributed under the License is distributed on an "AS IS" BASIS,
752 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
753 : See the License for the specific language governing permissions and
754 : limitations under the License.
755 : */
|