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 err_result = U8_ERROR_NONE;
137 : u8_error_t data_err;
138 :
139 : /* write report title */
140 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure a single root diagram\n" );
141 :
142 : /* get all root diagrams */
143 : uint32_t out_diagram_count;
144 30 : data_err = data_database_reader_get_diagrams_by_parent_id ( (*this_).db_reader,
145 : DATA_ROW_ID_VOID,
146 : CTRL_CONSISTENCY_CHECKER_MAX_DIAG_BUFFER,
147 30 : &((*this_).temp_diagram_buffer),
148 : &out_diagram_count
149 : );
150 :
151 30 : if ( U8_ERROR_NONE == data_err )
152 : {
153 30 : utf8stream_writer_write_str( out_english_report, " ROOT DIAGRAM COUNT: " );
154 30 : utf8stream_writer_write_int( out_english_report, out_diagram_count );
155 30 : utf8stream_writer_write_str( out_english_report, "\n" );
156 62 : for ( int list_pos = 0; list_pos < out_diagram_count; list_pos ++ )
157 : {
158 32 : utf8stream_writer_write_str( out_english_report, " INFO: Root diagram: " );
159 32 : utf8stream_writer_write_int( out_english_report, data_diagram_get_row_id( &((*this_).temp_diagram_buffer[list_pos]) ) );
160 32 : utf8stream_writer_write_str( out_english_report, ": " );
161 32 : utf8stream_writer_write_str( out_english_report, data_diagram_get_name_const( &((*this_).temp_diagram_buffer[list_pos]) ) );
162 32 : utf8stream_writer_write_str( out_english_report, "\n" );
163 : }
164 30 : if ( out_diagram_count == 0 )
165 : {
166 0 : (*io_err) ++;
167 0 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Create a diagram via the GUI.\n" );
168 : }
169 30 : else if ( out_diagram_count > 1 )
170 : {
171 2 : (*io_err) += (out_diagram_count-1) ;
172 2 : data_row_id_t proposed_root_diagram_id = data_diagram_get_row_id( &((*this_).temp_diagram_buffer[0]) );
173 2 : if ( ! modify_db )
174 : {
175 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Attach additional root diagrams below the first: " );
176 1 : utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id );
177 1 : utf8stream_writer_write_str( out_english_report, "\n" );
178 : }
179 : else
180 : {
181 2 : for ( int list_pos = 1; list_pos < out_diagram_count; list_pos ++ )
182 : {
183 1 : data_err = data_database_writer_update_diagram_parent_id ( (*this_).db_writer,
184 1 : data_diagram_get_row_id( &((*this_).temp_diagram_buffer[list_pos]) ),
185 : proposed_root_diagram_id,
186 : NULL
187 : );
188 1 : if ( U8_ERROR_NONE == data_err )
189 : {
190 1 : utf8stream_writer_write_str( out_english_report, " FIX: Diagram " );
191 1 : utf8stream_writer_write_int( out_english_report, data_diagram_get_row_id( &((*this_).temp_diagram_buffer[list_pos]) ) );
192 1 : utf8stream_writer_write_str( out_english_report, " attached to " );
193 1 : utf8stream_writer_write_int( out_english_report, proposed_root_diagram_id);
194 1 : utf8stream_writer_write_str( out_english_report, "\n" );
195 1 : (*io_fix) ++;
196 : }
197 : else
198 : {
199 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
200 0 : err_result |= data_err;
201 : }
202 : }
203 : }
204 : }
205 : }
206 : else
207 : {
208 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
209 0 : err_result |= data_err;
210 : }
211 :
212 30 : U8_TRACE_END_ERR( err_result );
213 30 : return err_result;
214 : }
215 :
216 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagram_parents ( ctrl_consistency_checker_t *this_,
217 : bool modify_db,
218 : uint32_t *io_err,
219 : uint32_t *io_fix,
220 : utf8stream_writer_t *out_english_report )
221 : {
222 30 : U8_TRACE_BEGIN();
223 30 : assert ( NULL != io_err );
224 30 : assert ( NULL != out_english_report );
225 30 : u8_error_t err_result = U8_ERROR_NONE;
226 : u8_error_t data_err;
227 :
228 : /* write report title */
229 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that no circular/invalid references of diagram parents exist\n" );
230 :
231 : data_small_set_t circ_ref;
232 30 : data_small_set_init( &circ_ref );
233 30 : data_err = data_database_consistency_checker_find_circular_diagram_parents ( &((*this_).db_checker), &circ_ref );
234 30 : if ( U8_ERROR_NONE == data_err )
235 : {
236 30 : uint32_t circ_ref_count = data_small_set_get_count( &circ_ref );
237 :
238 30 : utf8stream_writer_write_str( out_english_report, " DIAGRAMS WITH CIRCLUAR OR INVALID PARENT REFERENCES: " );
239 30 : utf8stream_writer_write_int( out_english_report, circ_ref_count );
240 30 : utf8stream_writer_write_str( out_english_report, "\n" );
241 :
242 30 : if ( circ_ref_count != 0 )
243 : {
244 4 : (*io_err) += circ_ref_count;
245 :
246 : /* get the root diagram */
247 4 : data_row_id_t root_diag_id = DATA_ROW_ID_VOID;
248 : {
249 : uint32_t out_diagram_count;
250 4 : data_err = data_database_reader_get_diagrams_by_parent_id ( (*this_).db_reader,
251 : DATA_ROW_ID_VOID,
252 : CTRL_CONSISTENCY_CHECKER_MAX_DIAG_BUFFER,
253 4 : &((*this_).temp_diagram_buffer),
254 : &out_diagram_count
255 : );
256 4 : if (( U8_ERROR_NONE == data_err )&&( out_diagram_count > 0 ))
257 : {
258 4 : root_diag_id = data_diagram_get_row_id( &((*this_).temp_diagram_buffer[0]) );
259 : }
260 : }
261 :
262 4 : if ( ! modify_db )
263 : {
264 2 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Move " );
265 2 : utf8stream_writer_write_int( out_english_report, circ_ref_count );
266 2 : utf8stream_writer_write_str( out_english_report, " diagrams below root diagram " );
267 2 : utf8stream_writer_write_int( out_english_report, root_diag_id );
268 2 : utf8stream_writer_write_str( out_english_report, ".\n" );
269 : }
270 : else
271 : {
272 6 : for ( int list_pos = 0; list_pos < circ_ref_count; list_pos ++ )
273 : {
274 4 : data_id_t diagram_id = data_small_set_get_id( &circ_ref, list_pos );
275 4 : data_row_id_t diagram_row_id = data_id_get_row_id( &diagram_id );
276 :
277 4 : data_err = data_database_writer_update_diagram_parent_id ( (*this_).db_writer,
278 : diagram_row_id,
279 : root_diag_id,
280 : NULL /*out_old_diagram*/
281 : );
282 4 : if ( U8_ERROR_NONE == data_err )
283 : {
284 4 : utf8stream_writer_write_str( out_english_report, " FIX: Diagram " );
285 4 : utf8stream_writer_write_int( out_english_report, diagram_row_id );
286 4 : utf8stream_writer_write_str( out_english_report, " moved below root diagram " );
287 4 : utf8stream_writer_write_int( out_english_report, root_diag_id );
288 4 : utf8stream_writer_write_str( out_english_report, ".\n" );
289 4 : (*io_fix) ++;
290 : }
291 : else
292 : {
293 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
294 0 : err_result |= data_err;
295 : }
296 : }
297 : }
298 : }
299 : }
300 : else
301 : {
302 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
303 0 : err_result |= data_err;
304 : }
305 :
306 30 : U8_TRACE_END_ERR( err_result );
307 30 : return err_result;
308 : }
309 :
310 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagramelements ( ctrl_consistency_checker_t *this_,
311 : bool modify_db,
312 : uint32_t *io_err,
313 : uint32_t *io_fix,
314 : utf8stream_writer_t *out_english_report )
315 : {
316 30 : U8_TRACE_BEGIN();
317 30 : assert ( NULL != io_err );
318 30 : assert ( NULL != io_fix );
319 30 : assert ( NULL != out_english_report );
320 30 : u8_error_t err_result = U8_ERROR_NONE;
321 : u8_error_t data_err;
322 :
323 : /* write report title */
324 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference valid diagrams and classifiers\n" );
325 :
326 : data_small_set_t unref;
327 30 : data_small_set_init( &unref );
328 30 : data_err = data_database_consistency_checker_find_nonreferencing_diagramelements ( &((*this_).db_checker), &unref );
329 30 : if ( U8_ERROR_NONE == data_err )
330 : {
331 30 : uint32_t unref_count = data_small_set_get_count( &unref );
332 :
333 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING DIAGRAMELEMENTS COUNT: " );
334 30 : utf8stream_writer_write_int( out_english_report, unref_count );
335 30 : utf8stream_writer_write_str( out_english_report, "\n" );
336 :
337 30 : if ( unref_count != 0 )
338 : {
339 2 : (*io_err) += unref_count;
340 :
341 2 : if ( ! modify_db )
342 : {
343 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
344 1 : utf8stream_writer_write_int( out_english_report, unref_count );
345 1 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
346 : }
347 : else
348 : {
349 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
350 : {
351 3 : data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
352 3 : data_row_id_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
353 3 : data_err = data_database_writer_delete_diagramelement ( (*this_).db_writer, diagramelement_row_id, NULL );
354 3 : if ( U8_ERROR_NONE == data_err )
355 : {
356 3 : utf8stream_writer_write_str( out_english_report, " FIX: Diagramelement " );
357 3 : utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
358 3 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
359 3 : (*io_fix) ++;
360 : }
361 : else
362 : {
363 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
364 0 : err_result |= data_err;
365 : }
366 : }
367 : }
368 : }
369 : }
370 : else
371 : {
372 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
373 0 : err_result |= data_err;
374 : }
375 :
376 30 : U8_TRACE_END_ERR( err_result );
377 30 : return err_result;
378 : }
379 :
380 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_diagele_features ( ctrl_consistency_checker_t *this_,
381 : bool modify_db,
382 : uint32_t *io_err,
383 : uint32_t *io_fix,
384 : utf8stream_writer_t *out_english_report )
385 : {
386 30 : U8_TRACE_BEGIN();
387 30 : assert ( NULL != io_err );
388 30 : assert ( NULL != io_fix );
389 30 : assert ( NULL != out_english_report );
390 30 : u8_error_t err_result = U8_ERROR_NONE;
391 : u8_error_t data_err;
392 :
393 : /* write report title */
394 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that diagramelements reference NULL or valid features\n" );
395 :
396 : data_small_set_t unref;
397 30 : data_small_set_init( &unref );
398 30 : data_err = data_database_consistency_checker_find_invalid_focused_features ( &((*this_).db_checker), &unref );
399 30 : if ( U8_ERROR_NONE == data_err )
400 : {
401 30 : uint32_t unref_count = data_small_set_get_count( &unref );
402 :
403 30 : utf8stream_writer_write_str( out_english_report, " ILLREFERENCING DIAGRAMELEMENTS COUNT: " );
404 30 : utf8stream_writer_write_int( out_english_report, unref_count );
405 30 : utf8stream_writer_write_str( out_english_report, "\n" );
406 :
407 30 : if ( unref_count != 0 )
408 : {
409 2 : (*io_err) += unref_count;
410 :
411 2 : if ( ! modify_db )
412 : {
413 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Unlink focused features from " );
414 1 : utf8stream_writer_write_int( out_english_report, unref_count );
415 1 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
416 : }
417 : else
418 : {
419 3 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
420 : {
421 2 : data_id_t diagramelement_id = data_small_set_get_id( &unref, list_pos );
422 2 : data_row_id_t diagramelement_row_id = data_id_get_row_id( &diagramelement_id );
423 2 : data_err = data_database_writer_update_diagramelement_focused_feature_id ( (*this_).db_writer, diagramelement_row_id, DATA_ROW_ID_VOID, NULL );
424 2 : if ( U8_ERROR_NONE == data_err )
425 : {
426 2 : utf8stream_writer_write_str( out_english_report, " FIX: Focused features unlinked from " );
427 2 : utf8stream_writer_write_int( out_english_report, diagramelement_row_id );
428 2 : utf8stream_writer_write_str( out_english_report, " diagramelements.\n" );
429 2 : (*io_fix) ++;
430 : }
431 : else
432 : {
433 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
434 0 : err_result |= data_err;
435 : }
436 : }
437 : }
438 : }
439 : }
440 : else
441 : {
442 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
443 0 : err_result |= data_err;
444 : }
445 :
446 30 : U8_TRACE_END_ERR( err_result );
447 30 : return err_result;
448 : }
449 :
450 30 : u8_error_t ctrl_consistency_checker_private_ensure_referenced_classifiers ( ctrl_consistency_checker_t *this_,
451 : bool modify_db,
452 : uint32_t *io_err,
453 : uint32_t *io_fix,
454 : utf8stream_writer_t *out_english_report )
455 : {
456 30 : U8_TRACE_BEGIN();
457 30 : assert ( NULL != io_err );
458 30 : assert ( NULL != io_fix );
459 30 : assert ( NULL != out_english_report );
460 30 : u8_error_t err_result = U8_ERROR_NONE;
461 : u8_error_t data_err;
462 :
463 : /* write report title */
464 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that classifiers are referenced\n" );
465 :
466 : data_small_set_t unref;
467 30 : data_small_set_init( &unref );
468 30 : data_err = data_database_consistency_checker_find_unreferenced_classifiers ( &((*this_).db_checker), &unref );
469 30 : if ( U8_ERROR_NONE == data_err )
470 : {
471 30 : uint32_t unref_count = data_small_set_get_count( &unref );
472 :
473 30 : utf8stream_writer_write_str( out_english_report, " UNREFERENCED CLASSIFIER COUNT: " );
474 30 : utf8stream_writer_write_int( out_english_report, unref_count );
475 30 : utf8stream_writer_write_str( out_english_report, "\n" );
476 :
477 30 : if ( unref_count != 0 )
478 : {
479 4 : (*io_err) += unref_count;
480 :
481 4 : if ( ! modify_db )
482 : {
483 2 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
484 2 : utf8stream_writer_write_int( out_english_report, unref_count );
485 2 : utf8stream_writer_write_str( out_english_report, " classifiers.\n" );
486 : }
487 : else
488 : {
489 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
490 : {
491 2 : data_id_t classifier_id = data_small_set_get_id( &unref, list_pos );
492 2 : data_row_id_t classifier_row_id = data_id_get_row_id( &classifier_id );
493 2 : err_result |= data_database_consistency_checker_kill_classifier ( &((*this_).db_checker), classifier_row_id );
494 2 : if ( U8_ERROR_NONE == err_result )
495 : {
496 2 : utf8stream_writer_write_str( out_english_report, " FIX: Classifier " );
497 2 : utf8stream_writer_write_int( out_english_report, classifier_row_id );
498 2 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
499 2 : (*io_fix) ++;
500 : }
501 : else
502 : {
503 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
504 : }
505 : }
506 : }
507 : }
508 : }
509 : else
510 : {
511 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
512 0 : err_result |= data_err;
513 : }
514 :
515 30 : U8_TRACE_END_ERR( err_result );
516 30 : return err_result;
517 : }
518 :
519 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_feature_parents ( ctrl_consistency_checker_t *this_,
520 : bool modify_db,
521 : uint32_t *io_err,
522 : uint32_t *io_fix,
523 : utf8stream_writer_t *out_english_report )
524 : {
525 30 : U8_TRACE_BEGIN();
526 30 : assert ( NULL != io_err );
527 30 : assert ( NULL != io_fix );
528 30 : assert ( NULL != out_english_report );
529 30 : u8_error_t err_result = U8_ERROR_NONE;
530 : u8_error_t data_err;
531 :
532 : /* write report title */
533 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that features have valid classifiers\n" );
534 :
535 : data_small_set_t unref;
536 30 : data_small_set_init( &unref );
537 30 : data_err = data_database_consistency_checker_find_unreferenced_features ( &((*this_).db_checker), &unref );
538 30 : if ( U8_ERROR_NONE == data_err )
539 : {
540 30 : uint32_t unref_count = data_small_set_get_count( &unref );
541 :
542 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING FEATURES COUNT: " );
543 30 : utf8stream_writer_write_int( out_english_report, unref_count );
544 30 : utf8stream_writer_write_str( out_english_report, "\n" );
545 :
546 30 : if ( unref_count != 0 )
547 : {
548 3 : (*io_err) += unref_count;
549 :
550 3 : if ( ! modify_db )
551 : {
552 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
553 1 : utf8stream_writer_write_int( out_english_report, unref_count );
554 1 : utf8stream_writer_write_str( out_english_report, " features.\n" );
555 : }
556 : else
557 : {
558 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
559 : {
560 2 : data_id_t feature_id = data_small_set_get_id( &unref, list_pos );
561 2 : data_row_id_t feature_row_id = data_id_get_row_id( &feature_id );
562 2 : data_err = data_database_writer_delete_feature ( (*this_).db_writer, feature_row_id, NULL );
563 2 : if ( U8_ERROR_NONE == data_err )
564 : {
565 2 : utf8stream_writer_write_str( out_english_report, " FIX: Feature " );
566 2 : utf8stream_writer_write_int( out_english_report, feature_row_id );
567 2 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
568 2 : (*io_fix) ++;
569 : }
570 : else
571 : {
572 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
573 0 : err_result |= data_err;
574 : }
575 : }
576 : }
577 : }
578 : }
579 : else
580 : {
581 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
582 0 : err_result |= data_err;
583 : }
584 :
585 30 : U8_TRACE_END_ERR( err_result );
586 30 : return err_result;
587 : }
588 :
589 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_classifiers ( ctrl_consistency_checker_t *this_,
590 : bool modify_db,
591 : uint32_t *io_err,
592 : uint32_t *io_fix,
593 : utf8stream_writer_t *out_english_report )
594 : {
595 30 : U8_TRACE_BEGIN();
596 30 : assert ( NULL != io_err );
597 30 : assert ( NULL != io_fix );
598 30 : assert ( NULL != out_english_report );
599 30 : u8_error_t err_result = U8_ERROR_NONE;
600 : u8_error_t data_err;
601 :
602 : /* write report title */
603 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link valid classifiers\n" );
604 :
605 : data_small_set_t unref;
606 30 : data_small_set_init( &unref );
607 30 : data_err = data_database_consistency_checker_find_unreferenced_relationships ( &((*this_).db_checker), &unref );
608 30 : if ( U8_ERROR_NONE == data_err )
609 : {
610 30 : uint32_t unref_count = data_small_set_get_count( &unref );
611 :
612 30 : utf8stream_writer_write_str( out_english_report, " NONREFERENCING RELATIONSHIPS COUNT: " );
613 30 : utf8stream_writer_write_int( out_english_report, unref_count );
614 30 : utf8stream_writer_write_str( out_english_report, "\n" );
615 :
616 30 : if ( unref_count != 0 )
617 : {
618 3 : (*io_err) += unref_count;
619 :
620 3 : if ( ! modify_db )
621 : {
622 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
623 1 : utf8stream_writer_write_int( out_english_report, unref_count );
624 1 : utf8stream_writer_write_str( out_english_report, " relationships.\n" );
625 : }
626 : else
627 : {
628 6 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
629 : {
630 4 : data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
631 4 : data_row_id_t relation_row_id = data_id_get_row_id( &relationship_id );
632 4 : data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
633 4 : if ( U8_ERROR_NONE == data_err )
634 : {
635 4 : utf8stream_writer_write_str( out_english_report, " FIX: Relationship " );
636 4 : utf8stream_writer_write_int( out_english_report, relation_row_id );
637 4 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
638 4 : (*io_fix) ++;
639 : }
640 : else
641 : {
642 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
643 0 : err_result |= data_err;
644 : }
645 : }
646 : }
647 : }
648 : }
649 : else
650 : {
651 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
652 0 : err_result |= data_err;
653 : }
654 :
655 30 : U8_TRACE_END_ERR( err_result );
656 30 : return err_result;
657 : }
658 :
659 30 : u8_error_t ctrl_consistency_checker_private_ensure_valid_relationship_features ( ctrl_consistency_checker_t *this_,
660 : bool modify_db,
661 : uint32_t *io_err,
662 : uint32_t *io_fix,
663 : utf8stream_writer_t *out_english_report )
664 : {
665 30 : U8_TRACE_BEGIN();
666 30 : assert ( NULL != io_err );
667 30 : assert ( NULL != io_fix );
668 30 : assert ( NULL != out_english_report );
669 30 : u8_error_t err_result = U8_ERROR_NONE;
670 : u8_error_t data_err;
671 :
672 : /* write report title */
673 30 : utf8stream_writer_write_str( out_english_report, "STEP: Ensure that relationships link NULL or valid features\n" );
674 :
675 : data_small_set_t unref;
676 30 : data_small_set_init( &unref );
677 30 : data_err = data_database_consistency_checker_find_invalid_relationship_features ( &((*this_).db_checker), &unref );
678 30 : if ( U8_ERROR_NONE == data_err )
679 : {
680 30 : uint32_t unref_count = data_small_set_get_count( &unref );
681 :
682 30 : utf8stream_writer_write_str( out_english_report, " ILLREFERENCING RELATIONSHIPS COUNT: " );
683 30 : utf8stream_writer_write_int( out_english_report, unref_count );
684 30 : utf8stream_writer_write_str( out_english_report, "\n" );
685 :
686 30 : if ( unref_count != 0 )
687 : {
688 2 : (*io_err) += unref_count;
689 :
690 2 : if ( ! modify_db )
691 : {
692 1 : utf8stream_writer_write_str( out_english_report, " PROPOSED FIX: Delete " );
693 1 : utf8stream_writer_write_int( out_english_report, unref_count );
694 1 : utf8stream_writer_write_str( out_english_report, " relationships.\n" );
695 : }
696 : else
697 : {
698 4 : for ( int list_pos = 0; list_pos < unref_count; list_pos ++ )
699 : {
700 3 : data_id_t relationship_id = data_small_set_get_id( &unref, list_pos );
701 3 : data_row_id_t relation_row_id = data_id_get_row_id( &relationship_id );
702 3 : data_err = data_database_writer_delete_relationship ( (*this_).db_writer, relation_row_id, NULL );
703 3 : if ( U8_ERROR_NONE == data_err )
704 : {
705 3 : utf8stream_writer_write_str( out_english_report, " FIX: Relationship " );
706 3 : utf8stream_writer_write_int( out_english_report, relation_row_id );
707 3 : utf8stream_writer_write_str( out_english_report, " deleted.\n" );
708 3 : (*io_fix) ++;
709 : }
710 : else
711 : {
712 0 : utf8stream_writer_write_str( out_english_report, "ERROR WRITING DATABASE.\n" );
713 0 : err_result |= data_err;
714 : }
715 : }
716 : }
717 : }
718 : }
719 : else
720 : {
721 0 : utf8stream_writer_write_str( out_english_report, "ERROR READING DATABASE.\n" );
722 0 : err_result |= data_err;
723 : }
724 :
725 30 : U8_TRACE_END_ERR( err_result );
726 30 : return err_result;
727 : }
728 :
729 :
730 : /*
731 : Copyright 2016-2024 Andreas Warnke
732 :
733 : Licensed under the Apache License, Version 2.0 (the "License");
734 : you may not use this file except in compliance with the License.
735 : You may obtain a copy of the License at
736 :
737 : http://www.apache.org/licenses/LICENSE-2.0
738 :
739 : Unless required by applicable law or agreed to in writing, software
740 : distributed under the License is distributed on an "AS IS" BASIS,
741 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
742 : See the License for the specific language governing permissions and
743 : limitations under the License.
744 : */
|