Line data Source code
1 : /* File: data_visible_set.c; Copyright and License: see below */ 2 : 3 : #include "set/data_visible_set.h" 4 : #include "data_rules.h" 5 : #include "u8/u8_trace.h" 6 : #include <stdio.h> 7 : #include <stdlib.h> 8 : #include <assert.h> 9 : 10 17 : void data_visible_set_init( data_visible_set_t *this_ ) 11 : { 12 17 : U8_TRACE_BEGIN(); 13 17 : U8_TRACE_INFO_INT( "sizeof(data_visible_set_t):", sizeof(data_visible_set_t) ); 14 : 15 17 : data_diagram_init_empty( &((*this_).diagram) ); 16 17 : (*this_).visible_classifier_count = 0; 17 17 : (*this_).feature_count = 0; 18 17 : (*this_).relationship_count = 0; 19 : 20 17 : U8_TRACE_END(); 21 17 : } 22 : 23 1 : void data_visible_set_reinit( data_visible_set_t *this_ ) 24 : { 25 1 : U8_TRACE_BEGIN(); 26 : 27 1 : data_diagram_reinit_empty( &((*this_).diagram) ); 28 1 : data_visible_set_private_destroy_visible_classifiers( this_ ); 29 1 : data_visible_set_private_destroy_features( this_ ); 30 1 : data_visible_set_private_destroy_relationships( this_ ); 31 : 32 1 : U8_TRACE_END(); 33 : 34 1 : } 35 : 36 7 : void data_visible_set_destroy( data_visible_set_t *this_ ) 37 : { 38 7 : U8_TRACE_BEGIN(); 39 : 40 7 : data_diagram_destroy( &((*this_).diagram) ); 41 7 : data_visible_set_private_destroy_visible_classifiers( this_ ); 42 7 : data_visible_set_private_destroy_features( this_ ); 43 7 : data_visible_set_private_destroy_relationships( this_ ); 44 : 45 7 : U8_TRACE_END(); 46 7 : } 47 : 48 8 : u8_error_t data_visible_set_load( data_visible_set_t *this_, data_row_t diagram_id, data_database_reader_t *db_reader ) 49 : { 50 8 : U8_TRACE_BEGIN(); 51 8 : assert( NULL != db_reader ); 52 8 : u8_error_t result = U8_ERROR_NONE; 53 : 54 8 : if ( DATA_ROW_VOID == diagram_id ) 55 : { 56 : /* re-init */ 57 1 : data_diagram_reinit_empty( &((*this_).diagram) ); 58 : 59 1 : data_visible_set_private_destroy_visible_classifiers( this_ ); 60 1 : data_visible_set_private_destroy_features( this_ ); 61 1 : data_visible_set_private_destroy_relationships( this_ ); 62 : } 63 : else 64 : { 65 7 : data_diagram_destroy( &((*this_).diagram) ); 66 7 : data_visible_set_private_destroy_visible_classifiers( this_ ); 67 7 : data_visible_set_private_destroy_features( this_ ); 68 7 : data_visible_set_private_destroy_relationships( this_ ); 69 : 70 : data_rules_t rules; 71 7 : data_rules_init( &rules ); 72 : 73 : /* load diagram */ 74 : { 75 : const u8_error_t diag_err 76 7 : = data_database_reader_get_diagram_by_id ( db_reader, diagram_id, &((*this_).diagram) ); 77 7 : if ( u8_error_contains( diag_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 78 : { 79 0 : U8_LOG_ERROR( "U8_ERROR_STRING_BUFFER_EXCEEDED at loading a diagram" ); 80 : } 81 7 : if ( u8_error_more_than( diag_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 82 : { 83 : /* error at loading */ 84 1 : data_diagram_reinit_empty( &((*this_).diagram) ); 85 : } 86 7 : result |= diag_err; /* collect error flags */ 87 : } 88 : 89 : /* load classifiers */ 90 : { 91 7 : u8_error_t c_err = U8_ERROR_NONE; 92 7 : (*this_).visible_classifier_count = 0; 93 : data_visible_classifier_iterator_t visible_classifier_iterator; 94 7 : c_err |= data_visible_classifier_iterator_init_empty( &visible_classifier_iterator ); 95 7 : c_err |= data_database_reader_get_visible_classifiers_by_diagram_id( db_reader, 96 : diagram_id, 97 : &visible_classifier_iterator 98 : ); 99 193 : while ( data_visible_classifier_iterator_has_next( &visible_classifier_iterator ) 100 193 : && ( ! u8_error_more_than( c_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) ) 101 : { 102 186 : if ( (*this_).visible_classifier_count < DATA_VISIBLE_SET_MAX_CLASSIFIERS ) 103 : { 104 185 : data_visible_classifier_t *const current_visible_classifier 105 185 : = &((*this_).visible_classifiers[(*this_).visible_classifier_count]); 106 185 : c_err |= data_visible_classifier_iterator_next( &visible_classifier_iterator, 107 : current_visible_classifier 108 : ); 109 185 : if ( ! u8_error_more_than( c_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 110 : { 111 185 : (*this_).visible_classifier_count ++; 112 : } 113 : } 114 : else 115 : { 116 1 : c_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED; 117 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading visible classifiers of a diagram" ); 118 : } 119 : } 120 7 : c_err |= data_visible_classifier_iterator_destroy( &visible_classifier_iterator ); 121 7 : result |= c_err; /* collect error flags */ 122 : } 123 : 124 : /* load features */ 125 : { 126 7 : u8_error_t f_err = U8_ERROR_NONE; 127 7 : (*this_).feature_count = 0; 128 : data_feature_iterator_t feature_iterator; 129 7 : f_err |= data_feature_iterator_init_empty( &feature_iterator ); 130 7 : f_err |= data_database_reader_get_features_by_diagram_id( db_reader, 131 : diagram_id, 132 : &feature_iterator 133 : ); 134 269 : while ( data_feature_iterator_has_next( &feature_iterator ) 135 269 : && ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) ) 136 : { 137 262 : if ( (*this_).feature_count < DATA_VISIBLE_SET_MAX_FEATURES ) 138 : { 139 261 : data_feature_t *const current_feature = &((*this_).features[(*this_).feature_count]); 140 261 : f_err |= data_feature_iterator_next( &feature_iterator, current_feature ); 141 261 : if ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 142 : { 143 : /* Ignore lifelines (== is_scenario) that do not belong to current diagram */ 144 : /* NOTE: The iteraltor already filters lifelines that do not belong to the current diagram, see DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_DIAGRAM_ID */ 145 : #if 0 146 : const bool is_scenario = 147 : data_rules_feature_is_scenario_cond( &rules, data_feature_get_main_type( current_feature ) ); 148 : bool is_foreign_scenario = is_scenario; 149 : for( uint_fast32_t vc_idx = 0; vc_idx < (*this_).visible_classifier_count; vc_idx ++ ) 150 : { 151 : const data_diagramelement_t *const diag_ele 152 : = data_visible_classifier_get_diagramelement_const( &((*this_).visible_classifiers[vc_idx]) ); 153 : const data_row_t focus_id = data_diagramelement_get_focused_feature_row_id( diag_ele ); 154 : if ( data_feature_get_row_id( current_feature ) == focus_id ) 155 : { 156 : is_foreign_scenario = false; 157 : } 158 : } 159 : if ( ! is_foreign_scenario ) /* either not a scenario or a scenario that is in scope of the diagram */ 160 : { 161 : #endif 162 261 : (*this_).feature_count++; 163 : #if 0 164 : } 165 : else 166 : { 167 : U8_TRACE_INFO_INT( "filtered a foreign scenario lifeline:", 168 : data_feature_get_row_id( current_feature ) 169 : ); 170 : } 171 : #endif 172 : } 173 : } 174 : else 175 : { 176 1 : f_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED; 177 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading features of a diagram" ); 178 : } 179 : } 180 7 : f_err |= data_feature_iterator_destroy( &feature_iterator ); 181 7 : result |= f_err; /* collect error flags */ 182 : } 183 : 184 : /* load relationships */ 185 : { 186 7 : u8_error_t r_err = U8_ERROR_NONE; 187 7 : (*this_).relationship_count = 0; 188 : data_relationship_iterator_t rel_iterator; 189 7 : r_err |= data_relationship_iterator_init_empty( &rel_iterator ); 190 7 : r_err |= data_database_reader_get_relationships_by_diagram_id( db_reader, 191 : diagram_id, 192 : &rel_iterator 193 : ); 194 402 : while ( data_relationship_iterator_has_next( &rel_iterator ) 195 402 : && ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) ) 196 : { 197 395 : if ( (*this_).relationship_count < DATA_VISIBLE_SET_MAX_RELATIONSHIPS ) 198 : { 199 394 : data_relationship_t *const current_relationship = &((*this_).relationships[(*this_).relationship_count]); 200 394 : r_err |= data_relationship_iterator_next( &rel_iterator, current_relationship ); 201 394 : if ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 202 : { 203 : /* Ignore relationships that have not both ends in current diagram - e.g. messages between foreign lifelines */ 204 394 : const data_row_t from_feat_row_id = data_relationship_get_from_feature_row_id( current_relationship ); 205 394 : const data_row_t to_feat_row_id = data_relationship_get_to_feature_row_id( current_relationship ); 206 394 : bool from_known = ( from_feat_row_id == DATA_ROW_VOID ); 207 394 : bool to_known = ( to_feat_row_id == DATA_ROW_VOID ); 208 98717 : for( uint_fast32_t f_idx = 0; f_idx < (*this_).feature_count; f_idx ++ ) 209 : { 210 98323 : const data_feature_t *const probe_feature = &((*this_).features[f_idx]); 211 98323 : const data_row_t probe_feat_id = data_feature_get_row_id( probe_feature ); 212 98323 : if ( probe_feat_id == from_feat_row_id ) 213 : { 214 4 : from_known = true; 215 : } 216 98323 : if ( probe_feat_id == to_feat_row_id ) 217 : { 218 3 : to_known = true; 219 : } 220 : } 221 394 : if ( from_known && to_known ) /* check that both relationship ends are in this data_visible_set_t */ 222 : { 223 391 : (*this_).relationship_count++; 224 : } 225 : else 226 : { 227 3 : U8_TRACE_INFO_INT( "filtered a foreign scenario message:", 228 : data_relationship_get_row_id( current_relationship ) 229 : ); 230 : } 231 : } 232 : } 233 : else 234 : { 235 1 : r_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED; 236 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading relationships of a diagram" ); 237 : } 238 : } 239 7 : r_err |= data_relationship_iterator_destroy( &rel_iterator ); 240 7 : result |= r_err; /* collect error flags */ 241 : } 242 : 243 7 : data_rules_destroy( &rules ); 244 : } 245 : 246 : /* update the containment cache */ 247 8 : data_visible_set_update_containment_cache( this_ ); 248 : 249 8 : U8_TRACE_END_ERR(result); 250 8 : return result; 251 : } 252 : 253 18 : void data_visible_set_update_containment_cache ( data_visible_set_t *this_ ) 254 : { 255 18 : U8_TRACE_BEGIN(); 256 18 : assert( (*this_).relationship_count <= DATA_VISIBLE_SET_MAX_RELATIONSHIPS ); 257 18 : assert( (*this_).visible_classifier_count <= DATA_VISIBLE_SET_MAX_CLASSIFIERS ); 258 : 259 : /* reset the containment array */ 260 18 : memset( &((*this_).containment_cache), '\0', sizeof( (*this_).containment_cache ) ); 261 : 262 : static const int MAX_SEARCH_PASSES = 4; /* with 4 passes, we can find ancesters and decendants which are related via 2*4=8 links and more */ 263 18 : bool new_containments_found = true; 264 : 265 36 : for ( int pass = 0; ( pass < MAX_SEARCH_PASSES ) && new_containments_found; pass ++ ) 266 : { 267 18 : new_containments_found = false; 268 : 269 2748 : for ( uint32_t rel_idx = 0; rel_idx < (*this_).relationship_count; rel_idx ++ ) 270 : { 271 : data_relationship_t *the_relationship; 272 2730 : the_relationship = &((*this_).relationships[rel_idx]); 273 : 274 : data_relationship_type_t the_type; 275 2730 : the_type = data_relationship_get_main_type ( the_relationship ); 276 : 277 2730 : if ( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == the_type ) 278 : { 279 : data_row_t parent_id; 280 : data_row_t child_id; 281 385 : parent_id = data_relationship_get_from_classifier_row_id ( the_relationship ); 282 385 : child_id = data_relationship_get_to_classifier_row_id ( the_relationship ); 283 : int32_t parent_index; 284 : int32_t child_index; 285 385 : parent_index = data_visible_set_get_classifier_index ( this_, parent_id ); 286 385 : child_index = data_visible_set_get_classifier_index ( this_, child_id ); 287 385 : if ( ( parent_index != -1 )&&( child_index != -1 ) ) 288 : { 289 385 : assert ( 0 <= parent_index ); 290 385 : assert ( parent_index < (*this_).visible_classifier_count ); 291 385 : assert ( 0 <= child_index ); 292 385 : assert ( child_index < (*this_).visible_classifier_count ); 293 : 294 : /* add the current relation to the containment_cache */ 295 385 : (*this_).containment_cache[parent_index][child_index] = true; 296 : 297 : /* all ancestors of parent are ancestors of child */ 298 49539 : for ( uint32_t ancestor_index = 0; ancestor_index < (*this_).visible_classifier_count; ancestor_index ++ ) 299 : { 300 49154 : if ( (*this_).containment_cache[ancestor_index][parent_index] ) 301 : { 302 0 : if ( ! (*this_).containment_cache[ancestor_index][child_index] ) 303 : { 304 0 : new_containments_found = true; 305 0 : (*this_).containment_cache[ancestor_index][child_index] = true; 306 : } 307 : } 308 : } 309 : 310 : /* all descendants of child are descendants of parent */ 311 49539 : for ( uint32_t descendant_index = 0; descendant_index < (*this_).visible_classifier_count; descendant_index ++ ) 312 : { 313 49154 : if ( (*this_).containment_cache[child_index][descendant_index] ) 314 : { 315 0 : if ( ! (*this_).containment_cache[parent_index][descendant_index] ) 316 : { 317 0 : new_containments_found = true; 318 0 : (*this_).containment_cache[parent_index][descendant_index] = true; 319 : } 320 : } 321 : } 322 : 323 : } 324 : /* else relation points outside the set of classifiers visible in current diagram */ 325 : } 326 : } 327 : } 328 : 329 18 : U8_TRACE_END(); 330 18 : } 331 : 332 : 333 : /* 334 : Copyright 2016-2025 Andreas Warnke 335 : 336 : Licensed under the Apache License, Version 2.0 (the "License"); 337 : you may not use this file except in compliance with the License. 338 : You may obtain a copy of the License at 339 : 340 : http://www.apache.org/licenses/LICENSE-2.0 341 : 342 : Unless required by applicable law or agreed to in writing, software 343 : distributed under the License is distributed on an "AS IS" BASIS, 344 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 345 : See the License for the specific language governing permissions and 346 : limitations under the License. 347 : */