LCOV - code coverage report
Current view: top level - data/source/set - data_visible_set.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 95.4 % 151 144
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 5 5

            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-2025 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              : */
        

Generated by: LCOV version 2.0-1