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 271 : while ( data_feature_iterator_has_next( &feature_iterator ) 135 271 : && ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) ) 136 : { 137 264 : if ( (*this_).feature_count < DATA_VISIBLE_SET_MAX_FEATURES ) 138 : { 139 263 : data_feature_t *const current_feature = &((*this_).features[(*this_).feature_count]); 140 263 : f_err |= data_feature_iterator_next( &feature_iterator, current_feature ); 141 263 : 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 : const bool is_scenario = 145 263 : data_rules_feature_is_scenario_cond( &rules, data_feature_get_main_type( current_feature ) ); 146 263 : bool is_foreign_scenario = is_scenario; 147 33045 : for( uint_fast32_t vc_idx = 0; vc_idx < (*this_).visible_classifier_count; vc_idx ++ ) 148 : { 149 : const data_diagramelement_t *const diag_ele 150 32782 : = data_visible_classifier_get_diagramelement_const( &((*this_).visible_classifiers[vc_idx]) ); 151 32782 : const data_row_t focus_id = data_diagramelement_get_focused_feature_row_id( diag_ele ); 152 32782 : if ( data_feature_get_row_id( current_feature ) == focus_id ) 153 : { 154 2 : is_foreign_scenario = false; 155 : } 156 : } 157 263 : if ( ! is_foreign_scenario ) /* either not a scenario or a scenario that is in scope of the diagram */ 158 : { 159 261 : (*this_).feature_count++; 160 : } 161 : else 162 : { 163 2 : U8_TRACE_INFO_INT( "filtered a foreign scenario lifeline:", 164 : data_feature_get_row_id( current_feature ) 165 : ); 166 : } 167 : } 168 : } 169 : else 170 : { 171 1 : f_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED; 172 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading features of a diagram" ); 173 : } 174 : } 175 7 : f_err |= data_feature_iterator_destroy( &feature_iterator ); 176 7 : result |= f_err; /* collect error flags */ 177 : } 178 : 179 : /* load relationships */ 180 : { 181 7 : u8_error_t r_err = U8_ERROR_NONE; 182 7 : (*this_).relationship_count = 0; 183 : data_relationship_iterator_t rel_iterator; 184 7 : r_err |= data_relationship_iterator_init_empty( &rel_iterator ); 185 7 : r_err |= data_database_reader_get_relationships_by_diagram_id( db_reader, 186 : diagram_id, 187 : &rel_iterator 188 : ); 189 402 : while ( data_relationship_iterator_has_next( &rel_iterator ) 190 402 : && ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) ) 191 : { 192 395 : if ( (*this_).relationship_count < DATA_VISIBLE_SET_MAX_RELATIONSHIPS ) 193 : { 194 394 : data_relationship_t *const current_relationship = &((*this_).relationships[(*this_).relationship_count]); 195 394 : r_err |= data_relationship_iterator_next( &rel_iterator, current_relationship ); 196 394 : if ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) 197 : { 198 : /* Ignore relationships that have not both ends in current diagram - e.g. messages between foreign lifelines */ 199 394 : const data_row_t from_feat_row_id = data_relationship_get_from_feature_row_id( current_relationship ); 200 394 : const data_row_t to_feat_row_id = data_relationship_get_to_feature_row_id( current_relationship ); 201 394 : bool from_known = ( from_feat_row_id == DATA_ROW_VOID ); 202 394 : bool to_known = ( to_feat_row_id == DATA_ROW_VOID ); 203 98717 : for( uint_fast32_t f_idx = 0; f_idx < (*this_).feature_count; f_idx ++ ) 204 : { 205 98323 : const data_feature_t *const probe_feature = &((*this_).features[f_idx]); 206 98323 : const data_row_t probe_feat_id = data_feature_get_row_id( probe_feature ); 207 98323 : if ( probe_feat_id == from_feat_row_id ) 208 : { 209 4 : from_known = true; 210 : } 211 98323 : if ( probe_feat_id == to_feat_row_id ) 212 : { 213 3 : to_known = true; 214 : } 215 : } 216 394 : if ( from_known && to_known ) /* check that both relationship ends are in this data_visible_set_t */ 217 : { 218 391 : (*this_).relationship_count++; 219 : } 220 : else 221 : { 222 3 : U8_TRACE_INFO_INT( "filtered a foreign scenario message:", 223 : data_relationship_get_row_id( current_relationship ) 224 : ); 225 : } 226 : } 227 : } 228 : else 229 : { 230 1 : r_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED; 231 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading relationships of a diagram" ); 232 : } 233 : } 234 7 : r_err |= data_relationship_iterator_destroy( &rel_iterator ); 235 7 : result |= r_err; /* collect error flags */ 236 : } 237 : 238 7 : data_rules_destroy( &rules ); 239 : } 240 : 241 : /* update the containment cache */ 242 8 : data_visible_set_update_containment_cache( this_ ); 243 : 244 8 : U8_TRACE_END_ERR(result); 245 8 : return result; 246 : } 247 : 248 18 : void data_visible_set_update_containment_cache ( data_visible_set_t *this_ ) 249 : { 250 18 : U8_TRACE_BEGIN(); 251 18 : assert( (*this_).relationship_count <= DATA_VISIBLE_SET_MAX_RELATIONSHIPS ); 252 18 : assert( (*this_).visible_classifier_count <= DATA_VISIBLE_SET_MAX_CLASSIFIERS ); 253 : 254 : /* reset the containment array */ 255 18 : memset( &((*this_).containment_cache), '\0', sizeof( (*this_).containment_cache ) ); 256 : 257 : 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 */ 258 18 : bool new_containments_found = true; 259 : 260 36 : for ( int pass = 0; ( pass < MAX_SEARCH_PASSES ) && new_containments_found; pass ++ ) 261 : { 262 18 : new_containments_found = false; 263 : 264 2748 : for ( uint32_t rel_idx = 0; rel_idx < (*this_).relationship_count; rel_idx ++ ) 265 : { 266 : data_relationship_t *the_relationship; 267 2730 : the_relationship = &((*this_).relationships[rel_idx]); 268 : 269 : data_relationship_type_t the_type; 270 2730 : the_type = data_relationship_get_main_type ( the_relationship ); 271 : 272 2730 : if ( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == the_type ) 273 : { 274 : data_row_t parent_id; 275 : data_row_t child_id; 276 385 : parent_id = data_relationship_get_from_classifier_row_id ( the_relationship ); 277 385 : child_id = data_relationship_get_to_classifier_row_id ( the_relationship ); 278 : int32_t parent_index; 279 : int32_t child_index; 280 385 : parent_index = data_visible_set_get_classifier_index ( this_, parent_id ); 281 385 : child_index = data_visible_set_get_classifier_index ( this_, child_id ); 282 385 : if ( ( parent_index != -1 )&&( child_index != -1 ) ) 283 : { 284 385 : assert ( 0 <= parent_index ); 285 385 : assert ( parent_index < (*this_).visible_classifier_count ); 286 385 : assert ( 0 <= child_index ); 287 385 : assert ( child_index < (*this_).visible_classifier_count ); 288 : 289 : /* add the current relation to the containment_cache */ 290 385 : (*this_).containment_cache[parent_index][child_index] = true; 291 : 292 : /* all ancestors of parent are ancestors of child */ 293 49539 : for ( uint32_t ancestor_index = 0; ancestor_index < (*this_).visible_classifier_count; ancestor_index ++ ) 294 : { 295 49154 : if ( (*this_).containment_cache[ancestor_index][parent_index] ) 296 : { 297 0 : if ( ! (*this_).containment_cache[ancestor_index][child_index] ) 298 : { 299 0 : new_containments_found = true; 300 0 : (*this_).containment_cache[ancestor_index][child_index] = true; 301 : } 302 : } 303 : } 304 : 305 : /* all descendants of child are descendants of parent */ 306 49539 : for ( uint32_t descendant_index = 0; descendant_index < (*this_).visible_classifier_count; descendant_index ++ ) 307 : { 308 49154 : if ( (*this_).containment_cache[child_index][descendant_index] ) 309 : { 310 0 : if ( ! (*this_).containment_cache[parent_index][descendant_index] ) 311 : { 312 0 : new_containments_found = true; 313 0 : (*this_).containment_cache[parent_index][descendant_index] = true; 314 : } 315 : } 316 : } 317 : 318 : } 319 : /* else relation points outside the set of classifiers visible in current diagram */ 320 : } 321 : } 322 : } 323 : 324 18 : U8_TRACE_END(); 325 18 : } 326 : 327 : 328 : /* 329 : Copyright 2016-2024 Andreas Warnke 330 : 331 : Licensed under the Apache License, Version 2.0 (the "License"); 332 : you may not use this file except in compliance with the License. 333 : You may obtain a copy of the License at 334 : 335 : http://www.apache.org/licenses/LICENSE-2.0 336 : 337 : Unless required by applicable law or agreed to in writing, software 338 : distributed under the License is distributed on an "AS IS" BASIS, 339 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 340 : See the License for the specific language governing permissions and 341 : limitations under the License. 342 : */