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.66.0_covts Lines: 95.1 % 142 135
Test Date: 2025-10-11 12:10:40 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          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              : */
        

Generated by: LCOV version 2.0-1