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_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 : data_relationship_iterator_t relationship_iterator; 83 5 : result |= data_relationship_iterator_init_empty( &relationship_iterator ); 84 5 : result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader, 85 : classifier_id, 86 : &relationship_iterator 87 : ); 88 5 : if ( result == U8_ERROR_NONE ) 89 : { 90 7 : while( data_relationship_iterator_has_next( &relationship_iterator ) ) 91 : { 92 2 : result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship_buf) ); 93 : 94 2 : bool visible = true; 95 : const u8_error_t vis_err 96 2 : = consistency_drop_invisibles_private_has_relationship_a_diagram( this_, &((*this_).temp_relationship_buf), &visible ); 97 : 98 2 : if ( vis_err == U8_ERROR_NONE ) 99 : { 100 2 : if ( ! visible ) 101 : { 102 : /* invisible relationship found */ 103 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */ 104 1 : const data_id_t relation_to_delete = data_relationship_get_data_id( &((*this_).temp_relationship_buf) ); 105 1 : result |= data_small_set_add_obj( &relations_to_delete, relation_to_delete ); 106 : } 107 : } 108 : else 109 : { 110 0 : result |= vis_err; 111 : } 112 : } 113 : } 114 : else 115 : { 116 0 : U8_LOG_WARNING( "Relationships of the deleted classifier cannot be checked for being superfluous now." ); 117 0 : U8_TRACE_INFO_INT( "classifier has unckecked relationships:", classifier_id ); 118 : } 119 5 : result |= data_relationship_iterator_destroy( &relationship_iterator ); 120 : /* note that relationship_iterator cannot be used here any longer due to re-entrancy by recursion */ 121 : 122 : /* delete all found relationship */ 123 5 : const uint32_t relations_count = data_small_set_get_count( &relations_to_delete ); 124 6 : for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ ) 125 : { 126 1 : const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 ); 127 1 : assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP ); 128 1 : result |= ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl, 129 : data_id_get_row_id( &delete_rel ), 130 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND 131 : ); 132 : } 133 : 134 5 : data_small_set_destroy( &relations_to_delete ); 135 : 136 5 : U8_TRACE_END_ERR( result ); 137 5 : return result; 138 : } 139 : 140 2 : u8_error_t consistency_drop_invisibles_private_has_relationship_a_diagram( consistency_drop_invisibles_t *this_, 141 : const data_relationship_t *relation, 142 : bool *out_result ) 143 : { 144 2 : U8_TRACE_BEGIN(); 145 2 : assert( NULL != relation ); 146 2 : assert( NULL != out_result ); 147 2 : u8_error_t result = U8_ERROR_NONE; 148 : 149 2 : const data_row_t from_classifier_id = data_relationship_get_from_classifier_row_id( relation ); 150 2 : const data_row_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation ); 151 : 152 2 : if ( from_classifier_id == to_classifier_id ) 153 : { 154 : /* relationship is visible in one diagram because source and destination are identical */ 155 0 : *out_result = true; 156 : } 157 : else 158 : { 159 2 : bool same_diag = false; 160 : data_small_set_t from_diagrams; 161 2 : data_small_set_init( &from_diagrams ); 162 : 163 : /* load diagramelements that are referenced by the relationships from end */ 164 : { 165 : data_diagramelement_iterator_t diagramelement_iterator; 166 2 : result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator ); 167 2 : result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader, 168 : from_classifier_id, 169 : &diagramelement_iterator 170 : ); 171 2 : if ( result == U8_ERROR_NONE ) 172 : { 173 4 : while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) ) 174 : { 175 2 : result |= data_diagramelement_iterator_next( &diagramelement_iterator, &((*this_).temp_diagelement_buf) ); 176 : const data_id_t from_diag_id 177 2 : = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) ); 178 : const u8_error_t ins_err 179 2 : = data_small_set_add_obj( &from_diagrams, from_diag_id ); 180 2 : if ( ins_err == U8_ERROR_DUPLICATE_ID ) 181 : { 182 : /* not an error */ 183 : } 184 : else 185 : { 186 2 : result |= ins_err; 187 : } 188 : } 189 : } 190 2 : result |= data_diagramelement_iterator_destroy( &diagramelement_iterator ); 191 : } 192 : 193 : /* load diagramelements that are referenced by the relationships to end */ 194 : data_diagramelement_iterator_t diagramelement_iterator2; 195 2 : result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator2 ); 196 2 : result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader, 197 : to_classifier_id, 198 : &diagramelement_iterator2 199 : ); 200 : 201 : /* check for same diagram */ 202 2 : if ( result == U8_ERROR_NONE ) 203 : { 204 5 : while ( data_diagramelement_iterator_has_next( &diagramelement_iterator2 ) ) 205 : { 206 3 : result |= data_diagramelement_iterator_next( &diagramelement_iterator2, &((*this_).temp_diagelement_buf) ); 207 : const data_id_t to_diag_id 208 3 : = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) ); 209 3 : if ( data_small_set_contains( &from_diagrams, to_diag_id ) ) 210 : { 211 1 : same_diag = true; 212 : } 213 : } 214 : } 215 2 : result |= data_diagramelement_iterator_destroy( &diagramelement_iterator2 ); 216 2 : data_small_set_destroy( &from_diagrams ); 217 : 218 2 : *out_result = same_diag; 219 : } 220 : 221 2 : U8_TRACE_END_ERR( result ); 222 2 : return result; 223 : } 224 : 225 : 226 : /* 227 : Copyright 2018-2024 Andreas Warnke 228 : 229 : Licensed under the Apache License, Version 2.0 (the "License"); 230 : you may not use this file except in compliance with the License. 231 : You may obtain a copy of the License at 232 : 233 : http://www.apache.org/licenses/LICENSE-2.0 234 : 235 : Unless required by applicable law or agreed to in writing, software 236 : distributed under the License is distributed on an "AS IS" BASIS, 237 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 238 : See the License for the specific language governing permissions and 239 : limitations under the License. 240 : */