LCOV - code coverage report
Current view: top level - data/source/set - data_visible_set.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 144 151 95.4 %
Date: 2024-12-21 18:34:41 Functions: 5 5 100.0 %

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

Generated by: LCOV version 1.16