Line data Source code
1 : /* File: consistency_drop_invisibles.c; Copyright and License: see below */ 2 : 3 : #include "consistency/consistency_drop_invisibles.h" 4 : #include "ctrl_classifier_controller.h" 5 : #include "ctrl_diagram_controller.h" 6 : #include "u8/u8_trace.h" 7 : #include "u8/u8_log.h" 8 : 9 42 : void consistency_drop_invisibles_init( consistency_drop_invisibles_t *this_, 10 : data_database_reader_t *db_reader, 11 : struct ctrl_classifier_controller_struct *clfy_ctrl, 12 : struct ctrl_diagram_controller_struct *diag_ctrl ) 13 : { 14 42 : U8_TRACE_BEGIN(); 15 42 : assert( NULL != db_reader ); 16 42 : assert( NULL != clfy_ctrl ); 17 42 : assert( NULL != diag_ctrl ); 18 : 19 42 : (*this_).db_reader = db_reader; 20 42 : (*this_).clfy_ctrl = clfy_ctrl; 21 42 : (*this_).diag_ctrl = diag_ctrl; 22 : 23 42 : U8_TRACE_END(); 24 42 : } 25 : 26 42 : void consistency_drop_invisibles_destroy( consistency_drop_invisibles_t *this_ ) 27 : { 28 42 : U8_TRACE_BEGIN(); 29 : 30 42 : (*this_).db_reader = NULL; 31 42 : (*this_).clfy_ctrl = NULL; 32 42 : (*this_).diag_ctrl = NULL; 33 : 34 42 : U8_TRACE_END(); 35 42 : } 36 : 37 : /* ================================ NO ABANDONED CLASSIFIERS ================================ */ 38 : 39 5 : u8_error_t consistency_drop_invisibles_delete_unreferenced_classifier( consistency_drop_invisibles_t *this_, 40 : const data_diagramelement_t *deleted_diagramelement ) 41 : { 42 5 : U8_TRACE_BEGIN(); 43 5 : assert( NULL != deleted_diagramelement ); 44 5 : u8_error_t result = U8_ERROR_NONE; 45 : 46 : /* try to also delete the classifier, ignore errors because it is ok if the classifier is still referenced */ 47 : u8_error_t my_ctrl_result; 48 : 49 5 : my_ctrl_result = ctrl_classifier_controller_delete_classifier( (*this_).clfy_ctrl, 50 : data_diagramelement_get_classifier_row_id( deleted_diagramelement ), 51 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND 52 : ); 53 : 54 5 : if ( u8_error_contains( my_ctrl_result, U8_ERROR_OBJECT_STILL_REFERENCED ) ) 55 : { 56 3 : U8_LOG_EVENT( "The classifier cannot be deleted because it is still referenced." ); 57 : } 58 : else 59 : { 60 : /* report this unexpected error */ 61 2 : result |= my_ctrl_result; 62 : } 63 : 64 5 : U8_TRACE_END_ERR( result ); 65 5 : return result; 66 : } 67 : 68 : /* ================================ NO INVISIBLE RELATIONSHIPS ================================ */ 69 : 70 5 : u8_error_t consistency_drop_invisibles_delete_invisible_relationships( consistency_drop_invisibles_t *this_, 71 : const data_diagramelement_t *deleted_diagramelement ) 72 : { 73 5 : U8_TRACE_BEGIN(); 74 5 : assert( NULL != deleted_diagramelement ); 75 5 : u8_error_t result = U8_ERROR_NONE; 76 : 77 5 : data_row_id_t classifier_id = data_diagramelement_get_classifier_row_id( deleted_diagramelement ); 78 : data_small_set_t relations_to_delete; 79 5 : data_small_set_init( &relations_to_delete ); 80 : 81 : /* load relationships to be checked */ 82 5 : uint32_t relationship_count = 0; 83 : const u8_error_t d_err 84 5 : = data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader, 85 : classifier_id, 86 : CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_RELATIONS, 87 5 : &((*this_).private_temp_rel_buf), 88 : &relationship_count 89 : ); 90 5 : if ( d_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED ) 91 : { 92 0 : U8_LOG_ANOMALY( "The dereferenced classifier has more relationships than can be checked for being superfluous now." ); 93 0 : U8_TRACE_INFO_INT( "classifier has too many relationships:", classifier_id ); 94 : /* no further error propagation. */ 95 : } 96 : else 97 : { 98 5 : result |= d_err; 99 : } 100 : 101 5 : if ( result == U8_ERROR_NONE ) 102 : { 103 7 : for ( uint_fast32_t rel_idx = 0; rel_idx < relationship_count; rel_idx ++ ) 104 : { 105 2 : const data_relationship_t *relation = &((*this_).private_temp_rel_buf[rel_idx]); 106 : 107 2 : bool visible = true; 108 : const u8_error_t vis_err 109 2 : = consistency_drop_invisibles_private_has_relationship_a_diagram( this_, relation, &visible ); 110 : 111 2 : if ( vis_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED ) 112 : { 113 0 : U8_LOG_ANOMALY( "A relationship is connected to a classifier that is too often referenced to check for being superfluous now." ); 114 0 : U8_TRACE_INFO_INT( "classifier or related classifier has too many diagramelements:", classifier_id ); 115 : /* no further error propagation. */ 116 : } 117 2 : else if ( vis_err == U8_ERROR_NONE ) 118 : { 119 2 : if ( ! visible ) 120 : { 121 : /* invisible relationship found */ 122 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */ 123 1 : result |= data_small_set_add_obj( &relations_to_delete, data_relationship_get_data_id( relation ) ); 124 : } 125 : } 126 : else 127 : { 128 0 : result |= vis_err; 129 : } 130 : } 131 : } 132 : 133 : /* delete all found relationship */ 134 : /* note that (*this_).private_temp_rel_buf cannot be used here any longer due to re-entrancy by recursion */ 135 5 : const uint32_t relations_count = data_small_set_get_count( &relations_to_delete ); 136 6 : for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ ) 137 : { 138 1 : const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 ); 139 1 : assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP ); 140 1 : result |= ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl, 141 : data_id_get_row_id( &delete_rel ), 142 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND 143 : ); 144 : } 145 : 146 5 : data_small_set_destroy( &relations_to_delete ); 147 : 148 5 : U8_TRACE_END_ERR( result ); 149 5 : return result; 150 : } 151 : 152 2 : u8_error_t consistency_drop_invisibles_private_has_relationship_a_diagram( consistency_drop_invisibles_t *this_, 153 : const data_relationship_t *relation, 154 : bool *out_result ) 155 : { 156 2 : U8_TRACE_BEGIN(); 157 2 : assert( NULL != relation ); 158 2 : assert( NULL != out_result ); 159 2 : u8_error_t result = U8_ERROR_NONE; 160 : 161 2 : const data_row_id_t from_classifier_id = data_relationship_get_from_classifier_row_id( relation ); 162 2 : const data_row_id_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation ); 163 : 164 2 : if ( from_classifier_id == to_classifier_id ) 165 : { 166 : /* relationship is visible in one diagram because source and destination are identical */ 167 0 : *out_result = true; 168 : } 169 : else 170 : { 171 : data_small_set_t from_diagrams; 172 2 : data_small_set_init( &from_diagrams ); 173 : u8_error_t from_err; 174 : 175 : /* load diagramelements that are referenced by the relationships from end */ 176 : { 177 2 : uint32_t from_diagramelement_count = 0; 178 : from_err 179 2 : = data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader, 180 : from_classifier_id, 181 : CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_DIAGELES, 182 2 : &((*this_).private_temp_diagele_buf), 183 : &from_diagramelement_count 184 : ); 185 2 : if ( from_err == U8_ERROR_NONE ) 186 : { 187 : /* copy diagram ids to id-set */ 188 4 : for ( uint_fast32_t from_idx = 0; from_idx < from_diagramelement_count; from_idx ++ ) 189 : { 190 : const data_id_t from_diag_id 191 2 : = data_diagramelement_get_diagram_data_id ( &((*this_).private_temp_diagele_buf[from_idx]) ); 192 : const u8_error_t ins_err 193 2 : = data_small_set_add_obj( &from_diagrams, from_diag_id ); 194 2 : if ( ins_err == U8_ERROR_DUPLICATE_ID ) 195 : { 196 : /* not an error */ 197 : } 198 : else 199 : { 200 2 : from_err |= ins_err; 201 : } 202 : } 203 : } 204 : } 205 : 206 : /* load diagramelements that are referenced by the relationships to end */ 207 2 : uint32_t to_diagramelement_count = 0; 208 : const u8_error_t to_err 209 2 : = data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader, 210 : to_classifier_id, 211 : CONSISTENCY_DROP_INVISIBLES_CONST_MAX_TEMP_DIAGELES, 212 2 : &((*this_).private_temp_diagele_buf), 213 : &to_diagramelement_count 214 : ); 215 : 216 : /* check for same diagram */ 217 2 : if (( from_err == U8_ERROR_NONE )&&( to_err == U8_ERROR_NONE )) 218 2 : { 219 2 : bool same_diag = false; 220 5 : for ( uint_fast32_t to_idx = 0; to_idx < to_diagramelement_count; to_idx ++ ) 221 : { 222 : const data_id_t to_diag_id 223 3 : = data_diagramelement_get_diagram_data_id ( &((*this_).private_temp_diagele_buf[to_idx]) ); 224 3 : if ( data_small_set_contains( &from_diagrams, to_diag_id ) ) 225 : { 226 1 : same_diag = true; 227 : } 228 : } 229 2 : *out_result = same_diag; 230 : } 231 : else 232 : { 233 0 : result |= from_err; 234 0 : result |= to_err; 235 : } 236 : 237 2 : data_small_set_destroy( &from_diagrams ); 238 : } 239 : 240 2 : U8_TRACE_END_ERR( result ); 241 2 : return result; 242 : } 243 : 244 : 245 : /* 246 : Copyright 2018-2024 Andreas Warnke 247 : 248 : Licensed under the Apache License, Version 2.0 (the "License"); 249 : you may not use this file except in compliance with the License. 250 : You may obtain a copy of the License at 251 : 252 : http://www.apache.org/licenses/LICENSE-2.0 253 : 254 : Unless required by applicable law or agreed to in writing, software 255 : distributed under the License is distributed on an "AS IS" BASIS, 256 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 257 : See the License for the specific language governing permissions and 258 : limitations under the License. 259 : */