LCOV - code coverage report
Current view: top level - io/source - io_export_model_traversal.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 0.0 % 321 0
Test Date: 2025-05-01 10:10:14 Functions: 0.0 % 12 0

            Line data    Source code
       1              : /* File: io_export_model_traversal.c; Copyright and License: see below */
       2              : 
       3              : #include "io_export_model_traversal.h"
       4              : #include "u8/u8_trace.h"
       5              : #include "entity/data_diagram.h"
       6              : #include "entity/data_classifier.h"
       7              : #include <stdint.h>
       8              : #include <stdio.h>
       9              : #include <stdlib.h>
      10              : 
      11            0 : void io_export_model_traversal_init( io_export_model_traversal_t *this_,
      12              :                                      data_database_reader_t *db_reader,
      13              :                                      data_visible_set_t *input_data,
      14              :                                      data_stat_t *io_export_stat,
      15              :                                      io_element_writer_t *out_element_writer )
      16              : {
      17            0 :     U8_TRACE_BEGIN();
      18            0 :     assert( NULL != db_reader );
      19            0 :     assert( NULL != io_export_stat );
      20            0 :     assert( NULL != out_element_writer );
      21              : 
      22            0 :     (*this_).db_reader = db_reader;
      23            0 :     (*this_).export_stat = io_export_stat;
      24            0 :     (*this_).element_writer = out_element_writer;
      25              : 
      26            0 :     universal_array_list_init ( &((*this_).written_id_set),
      27              :                                 sizeof((*this_).written_id_set_buf)/sizeof(data_id_t),
      28            0 :                                 &((*this_).written_id_set_buf),
      29              :                                 sizeof(data_id_t),
      30              :                                 ((char*)(&((*this_).written_id_set_buf[1])))-((char*)(&((*this_).written_id_set_buf[0]))),
      31              :                                 (void (*)(void *, const void *)) &data_id_copy,
      32              :                                 (bool (*)(const void *, const void *)) &data_id_equals,
      33              :                                 (void (*)(void *)) &data_id_destroy
      34              :                               );
      35              : 
      36            0 :     io_export_interaction_traversal_init( &((*this_).interaction_helper),
      37              :                                           db_reader,
      38              :                                           input_data,
      39              :                                           &((*this_).written_id_set),
      40              :                                           io_export_stat,
      41              :                                           out_element_writer
      42              :                                         );
      43            0 :     U8_TRACE_END();
      44            0 : }
      45              : 
      46            0 : void io_export_model_traversal_destroy( io_export_model_traversal_t *this_ )
      47              : {
      48            0 :     U8_TRACE_BEGIN();
      49              : 
      50            0 :     io_export_interaction_traversal_destroy ( &((*this_).interaction_helper) );
      51              : 
      52            0 :     universal_array_list_destroy ( &((*this_).written_id_set) );
      53              : 
      54            0 :     (*this_).db_reader = NULL;
      55            0 :     (*this_).export_stat = NULL;
      56            0 :     (*this_).element_writer = NULL;
      57              : 
      58            0 :     U8_TRACE_END();
      59            0 : }
      60              : 
      61            0 : u8_error_t io_export_model_traversal_walk_model_nodes ( io_export_model_traversal_t *this_ )
      62              : {
      63            0 :     U8_TRACE_BEGIN();
      64            0 :     u8_error_t write_err = U8_ERROR_NONE;
      65              : 
      66              :     {
      67              :         u8_error_t data_err;
      68              :         data_classifier_iterator_t classifier_iterator;
      69            0 :         universal_array_list_clear( &((*this_).written_id_set) );
      70              : 
      71              :         /* init the iterator */
      72            0 :         data_classifier_iterator_init_empty( &classifier_iterator );
      73            0 :         data_err = data_database_reader_get_all_classifiers ( (*this_).db_reader, true, &classifier_iterator );
      74            0 :         if ( data_err != U8_ERROR_NONE )
      75              :         {
      76            0 :             write_err |= data_err;
      77              :         }
      78              :         else
      79              :         {
      80            0 :             while( data_classifier_iterator_has_next( &classifier_iterator ) && ( write_err==0 ) )
      81              :             {
      82            0 :                 data_err = data_classifier_iterator_next( &classifier_iterator, &((*this_).temp_classifier) );
      83            0 :                 if ( data_err != U8_ERROR_NONE )
      84              :                 {
      85            0 :                     write_err |= data_err;
      86              :                 }
      87              :                 else
      88              :                 {
      89            0 :                     const data_id_t classifier_id = data_classifier_get_data_id( &((*this_).temp_classifier) );
      90            0 :                     data_classifier_destroy( &((*this_).temp_classifier) );
      91              : 
      92            0 :                     write_err |= io_export_model_traversal_private_walk_node( this_,
      93            0 :                                                                               DATA_ID_VOID,
      94            0 :                                                                               DATA_ID_VOID,
      95              :                                                                               classifier_id,
      96              :                                                                               0 /* initial recursion_depth */
      97              :                                                                             );
      98              :                 }
      99              :             }
     100              :         }
     101            0 :         data_err = data_classifier_iterator_destroy( &classifier_iterator );
     102            0 :         if ( data_err != U8_ERROR_NONE )
     103              :         {
     104            0 :             write_err |= data_err;
     105              :         }
     106              :     }
     107              : 
     108            0 :     U8_TRACE_END_ERR( write_err );
     109            0 :     return write_err;
     110              : }
     111              : 
     112            0 : u8_error_t io_export_model_traversal_private_walk_node( io_export_model_traversal_t *this_,
     113              :                                                         data_id_t host_id,
     114              :                                                         data_id_t containment_relationship_id,
     115              :                                                         data_id_t classifier_id,
     116              :                                                         unsigned int recursion_depth )
     117              : {
     118            0 :     U8_TRACE_BEGIN();
     119            0 :     assert( recursion_depth <= IO_EXPORT_MODEL_TRAVERSAL_MAX_TREE_DEPTH );
     120            0 :     assert( data_id_is_valid( &classifier_id ) );
     121            0 :     data_id_trace( &classifier_id );
     122            0 :     u8_error_t write_err = U8_ERROR_NONE;
     123              : 
     124              :     /* initially define flags and attributes */
     125            0 :     bool duplicate_classifier
     126            0 :         = ( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &classifier_id ) );
     127            0 :     bool is_classifier_compliant_here = false;  /* a default value */
     128              : 
     129              :     /* the id-sets needed on the stack during recursion */
     130              :     data_small_set_t contained_classifiers;
     131            0 :     data_small_set_init( &contained_classifiers );
     132              :     data_small_set_t containment_relations;
     133            0 :     data_small_set_init( &containment_relations );
     134              : 
     135              :     /* tasks before recursion */
     136            0 :     if ( ! duplicate_classifier )
     137              :     {
     138            0 :         const u8_error_t data_err_1
     139            0 :             = ( ! data_id_is_valid( &host_id ) )
     140              :             ? U8_ERROR_NONE
     141            0 :             : data_database_reader_get_classifier_by_id( (*this_).db_reader,
     142              :                                                          data_id_get_row_id( &host_id ),
     143              :                                                          &((*this_).temp_host)
     144              :                                                        );
     145              :         const u8_error_t data_err_2
     146            0 :             = data_database_reader_get_classifier_by_id( (*this_).db_reader,
     147              :                                                          data_id_get_row_id( &classifier_id ),
     148              :                                                          &((*this_).temp_classifier)
     149              :                                                        );
     150              : 
     151            0 :         if (( data_err_1 != U8_ERROR_NONE )||( data_err_2 != U8_ERROR_NONE ))
     152              :         {
     153            0 :             write_err |= data_err_1 | data_err_2;
     154              :         }
     155              :         else
     156              :         {
     157              :             /* update flags and attributes */
     158            0 :             const data_classifier_type_t host_type
     159            0 :                 = ( ! data_id_is_valid( &host_id ) )
     160              :                 ? DATA_CLASSIFIER_TYPE_PACKAGE   /* a uml:Model (the out-most model element) is a uml:Package*/
     161            0 :                 : data_classifier_get_main_type( &((*this_).temp_host) );
     162            0 :             const data_classifier_type_t classifier_type = data_classifier_get_main_type( &((*this_).temp_classifier) );
     163              : 
     164              :             /* fake and export interactions in which the current node is participant first */
     165              :             /* recursion trick: If classifier is nested, this block is evaluated
     166              :              * 1x for the nested classifier and 1x for same classifier at the toplevel model package
     167              :              */
     168              :             {
     169              :                 /* write the relationships that can be stated after the classifier or in the toplevel package */
     170            0 :                 write_err |= io_export_model_traversal_private_fake_interactions_of_node( this_,
     171              :                                                                                           host_type,
     172            0 :                                                                                           &((*this_).temp_classifier)
     173              :                                                                                         );
     174              :                 /* check if the classifier is already written */
     175              :                 duplicate_classifier
     176            0 :                     =( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &classifier_id ) );
     177              :             }
     178              : 
     179            0 :             is_classifier_compliant_here = io_element_writer_can_classifier_nest_classifier( (*this_).element_writer,
     180              :                                                                                              host_type,
     181              :                                                                                              classifier_type
     182              :                                                                                            );
     183            0 :             if (( recursion_depth == 0 )&&( !is_classifier_compliant_here ))
     184              :             {
     185              :                 /* fallback, there is no other place to put the classifier */
     186            0 :                 is_classifier_compliant_here = true;
     187              :             }
     188              : 
     189            0 :             if (( ! duplicate_classifier )&&( is_classifier_compliant_here ))
     190              :             {
     191              :                 /* add this classifier to the already written elements */
     192            0 :                 write_err |= universal_array_list_append( &((*this_).written_id_set), &classifier_id );
     193              :                 /* if this classifier was found via a containment_relationship, */
     194              :                 /* add this containment_relationship to the already written elements */
     195            0 :                 if ( data_id_is_valid( &containment_relationship_id ) )
     196              :                 {
     197            0 :                     write_err |= universal_array_list_append( &((*this_).written_id_set), &containment_relationship_id );
     198              :                 }
     199              : 
     200              :                 /* walk node which is not a duplicate */
     201            0 :                 write_err |= io_export_model_traversal_private_begin_node( this_,
     202              :                                                                            host_type,
     203            0 :                                                                            &((*this_).temp_classifier)
     204              :                                                                          );
     205              : 
     206            0 :                 write_err |= io_export_model_traversal_private_iterate_node_features( this_, &((*this_).temp_classifier) );
     207              : 
     208            0 :                 write_err |= io_export_model_traversal_private_get_containments( this_,
     209            0 :                                                                                  &((*this_).temp_classifier),
     210              :                                                                                  &contained_classifiers,
     211              :                                                                                  &containment_relations
     212              :                                                                                );
     213              :             }
     214              :         }
     215              : 
     216            0 :         if ( data_id_is_valid( &host_id ) )
     217              :         {
     218            0 :             data_classifier_destroy( &((*this_).temp_host) );
     219              :         }
     220            0 :         data_classifier_destroy( &((*this_).temp_classifier) );
     221              :     }
     222              : 
     223              :     /* do recursion, all required data is stored on the stack now */
     224            0 :     if (( ! duplicate_classifier )&&( is_classifier_compliant_here ))
     225              :     {
     226            0 :         write_err |= io_export_model_traversal_private_walk_containments( this_,
     227              :                                                                           classifier_id,
     228              :                                                                           &contained_classifiers,
     229              :                                                                           &containment_relations,
     230              :                                                                           recursion_depth
     231              :                                                                         );
     232              :     }
     233              : 
     234              :     /* tasks after recursion */
     235              :     {
     236            0 :         const u8_error_t data_err_3
     237            0 :             = ( ! data_id_is_valid( &host_id ) )
     238              :             ? U8_ERROR_NONE
     239            0 :             : data_database_reader_get_classifier_by_id( (*this_).db_reader,
     240              :                                                          data_id_get_row_id( &host_id ),
     241              :                                                          &((*this_).temp_host)
     242              :                                                        );
     243              :         const u8_error_t data_err_4
     244            0 :             = data_database_reader_get_classifier_by_id( (*this_).db_reader,
     245              :                                                          data_id_get_row_id( &classifier_id ),
     246              :                                                          &((*this_).temp_classifier)
     247              :                                                        );
     248              : 
     249            0 :         if (( data_err_3 != U8_ERROR_NONE )||( data_err_4 != U8_ERROR_NONE ))
     250              :         {
     251            0 :             write_err |= data_err_3 | data_err_4;
     252              :         }
     253              :         else
     254              :         {
     255            0 :             const data_classifier_type_t host_type_2
     256            0 :                 = ( ! data_id_is_valid( &host_id ) )
     257              :                 ? DATA_CLASSIFIER_TYPE_PACKAGE   /* a uml:Model is a uml:Package*/
     258            0 :                 : data_classifier_get_main_type( &((*this_).temp_host) );
     259            0 :             const data_classifier_t *host_2
     260            0 :                 = ( ! data_id_is_valid( &host_id ) )
     261              :                 ? NULL
     262            0 :                 : &((*this_).temp_host);
     263              : 
     264            0 :             if (( ! duplicate_classifier )&&( is_classifier_compliant_here ))
     265              :             {
     266              :                 /* write the relationships that can be nested within the classifier */
     267            0 :                 write_err |= io_export_model_traversal_private_iterate_node_relationships( this_,
     268              :                                                                                            false,
     269            0 :                                                                                            &((*this_).temp_classifier),  /* inside here */
     270            0 :                                                                                            &((*this_).temp_classifier)
     271              :                                                                                          );
     272              : 
     273            0 :                 write_err |= io_export_model_traversal_private_end_node( this_,
     274              :                                                                          host_type_2,
     275            0 :                                                                          &((*this_).temp_classifier)
     276              :                                                                        );
     277              :             }
     278              : 
     279              :             /* recursion trick: If from- and to- classifiers are nested, this block is evaluated
     280              :              * 1x for the nested from-/to- classifier and 1x for same classifier at the toplevel model package
     281              :              */
     282              :             {
     283              :                 /* write the relationships that can be stated after the classifier or in the toplevel package */
     284            0 :                 write_err |= io_export_model_traversal_private_iterate_node_relationships( this_,
     285              :                                                                                            true,
     286              :                                                                                            host_2,  /* outside now */
     287            0 :                                                                                            &((*this_).temp_classifier)
     288              :                                                                                          );
     289              :             }
     290              :         }
     291              : 
     292            0 :         if ( data_id_is_valid( &host_id ) )
     293              :         {
     294            0 :             data_classifier_destroy( &((*this_).temp_host) );
     295              :         }
     296            0 :         data_classifier_destroy( &((*this_).temp_classifier) );
     297              :     }
     298              : 
     299            0 :     data_small_set_destroy( &contained_classifiers );
     300            0 :     data_small_set_destroy( &containment_relations );
     301              : 
     302            0 :     U8_TRACE_END_ERR( write_err );
     303            0 :     return write_err;
     304              : }
     305              : 
     306            0 : u8_error_t io_export_model_traversal_private_begin_node ( io_export_model_traversal_t *this_,
     307              :                                                           data_classifier_type_t host_type,
     308              :                                                           const data_classifier_t *classifier )
     309              : {
     310            0 :     U8_TRACE_BEGIN();
     311            0 :     assert( classifier != NULL );
     312            0 :     u8_error_t write_err = U8_ERROR_NONE;
     313              : 
     314            0 :     write_err |= io_element_writer_start_classifier( (*this_).element_writer, host_type, classifier );
     315            0 :     write_err |= io_element_writer_assemble_classifier( (*this_).element_writer, host_type, classifier );
     316              : 
     317            0 :     U8_TRACE_END_ERR( write_err );
     318            0 :     return write_err;
     319              : }
     320              : 
     321            0 : u8_error_t io_export_model_traversal_private_get_containments( io_export_model_traversal_t *this_,
     322              :                                                                const data_classifier_t *classifier,
     323              :                                                                data_small_set_t *io_contained_classifiers,
     324              :                                                                data_small_set_t *io_containment_relations )
     325              : {
     326            0 :     U8_TRACE_BEGIN();
     327            0 :     assert( classifier != NULL );
     328            0 :     assert( io_contained_classifiers != NULL );
     329            0 :     assert( io_containment_relations != NULL );
     330            0 :     u8_error_t result = U8_ERROR_NONE;
     331              : 
     332            0 :     const data_id_t classifier_id = data_classifier_get_data_id( classifier );
     333            0 :     data_id_trace( &classifier_id );
     334              : 
     335              :     /* search containments in relationships */
     336              :     data_relationship_iterator_t rel_iterator;
     337            0 :     result |= data_relationship_iterator_init_empty( &rel_iterator );
     338            0 :     result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
     339              :                                                                        data_classifier_get_row_id( classifier ),
     340              :                                                                        &rel_iterator
     341              :                                                                      );
     342              : 
     343            0 :     while ( data_relationship_iterator_has_next( &rel_iterator ) )
     344              :     {
     345              :         /* get relationship */
     346            0 :         result |= data_relationship_iterator_next( &rel_iterator, &((*this_).temp_relationship) );
     347            0 :         if ( data_relationship_is_valid( &((*this_).temp_relationship) ) )
     348              :         {
     349            0 :             const data_id_t from_classifier_id = data_relationship_get_from_classifier_data_id( &((*this_).temp_relationship) );
     350            0 :             const bool container_is_this = data_id_equals( &from_classifier_id, &classifier_id );
     351            0 :             const bool is_containment
     352            0 :                 = ( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == data_relationship_get_main_type( &((*this_).temp_relationship) ) );
     353            0 :             if ( container_is_this && is_containment )
     354              :             {
     355            0 :                 const data_id_t relationship_id = data_relationship_get_data_id( &((*this_).temp_relationship) );
     356            0 :                 const data_id_t from_feature_id = data_relationship_get_from_feature_data_id( &((*this_).temp_relationship) );
     357            0 :                 const data_id_t to_feature_id = data_relationship_get_to_feature_data_id( &((*this_).temp_relationship) );
     358            0 :                 const data_id_t to_classifier_id = data_relationship_get_to_classifier_data_id( &((*this_).temp_relationship) );
     359            0 :                 if ( data_id_is_valid( &from_feature_id ) )
     360              :                 {
     361            0 :                     U8_TRACE_INFO("Anomaly: A feature of this classifier contains something");
     362              :                 }
     363            0 :                 else if ( data_id_is_valid( &to_feature_id ) )
     364              :                 {
     365            0 :                     U8_TRACE_INFO("Anomaly: This classifier contains a feature");
     366              :                 }
     367            0 :                 else if ( data_id_equals( &to_classifier_id, &classifier_id ) )
     368              :                 {
     369            0 :                     U8_TRACE_INFO("Anomaly: This classifier contains itself");
     370              :                 }
     371            0 :                 else if ( data_small_set_contains( io_contained_classifiers, to_classifier_id ) )
     372              :                 {
     373            0 :                     U8_TRACE_INFO("Anomaly: This classifier contains a child twice");
     374              :                 }
     375              :                 else
     376              :                 {
     377            0 :                     data_small_set_add_obj ( io_contained_classifiers, to_classifier_id );
     378            0 :                     data_small_set_add_obj ( io_containment_relations, relationship_id );
     379              :                 }
     380              :             }
     381              :         }
     382              :         else
     383              :         {
     384            0 :             assert( false );
     385              :         }
     386              :     }
     387            0 :     result |= data_relationship_iterator_destroy( &rel_iterator );
     388              : 
     389            0 :     U8_TRACE_END_ERR( result );
     390            0 :     return result;
     391              : }
     392              : 
     393            0 : u8_error_t io_export_model_traversal_private_walk_containments ( io_export_model_traversal_t *this_,
     394              :                                                                  data_id_t host_id,
     395              :                                                                  const data_small_set_t *contained_classifiers,
     396              :                                                                  const data_small_set_t *containment_relations,
     397              :                                                                  unsigned int recursion_depth )
     398              : {
     399            0 :     U8_TRACE_BEGIN();
     400            0 :     assert( contained_classifiers != NULL );
     401            0 :     assert( containment_relations != NULL );
     402            0 :     data_id_trace( &host_id );
     403            0 :     u8_error_t write_err = U8_ERROR_NONE;
     404              : 
     405              :     /* do recursion */
     406            0 :     if ( recursion_depth < IO_EXPORT_MODEL_TRAVERSAL_MAX_TREE_DEPTH )
     407              :     {
     408            0 :         const uint32_t children = data_small_set_get_count ( contained_classifiers );
     409            0 :         U8_TRACE_INFO_INT( "Children: ", children );
     410            0 :         assert( children == data_small_set_get_count ( containment_relations ) );
     411            0 :         for ( uint32_t index = 0; index < children; index ++ )
     412              :         {
     413            0 :             const data_id_t child = data_small_set_get_id ( contained_classifiers, index );
     414            0 :             const data_id_t c_rel = data_small_set_get_id ( containment_relations, index );
     415            0 :             write_err |= io_export_model_traversal_private_walk_node( this_, host_id, c_rel, child, recursion_depth+1 );
     416              :         }
     417              :     }
     418              : 
     419            0 :     U8_TRACE_END_ERR( write_err );
     420            0 :     return write_err;
     421              : }
     422              : 
     423            0 : u8_error_t io_export_model_traversal_private_end_node ( io_export_model_traversal_t *this_,
     424              :                                                         data_classifier_type_t host_type,
     425              :                                                         const data_classifier_t *classifier )
     426              : {
     427            0 :     U8_TRACE_BEGIN();
     428            0 :     assert( classifier != NULL );
     429            0 :     u8_error_t write_err = U8_ERROR_NONE;
     430              : 
     431            0 :     write_err |= io_element_writer_end_classifier( (*this_).element_writer, host_type, classifier );
     432              : 
     433            0 :     U8_TRACE_END_ERR( write_err );
     434            0 :     return write_err;
     435              : }
     436              : 
     437            0 : u8_error_t io_export_model_traversal_private_iterate_node_features ( io_export_model_traversal_t *this_,
     438              :                                                                      const data_classifier_t *classifier )
     439              : {
     440            0 :     U8_TRACE_BEGIN();
     441            0 :     assert( classifier != NULL );
     442            0 :     assert( data_classifier_is_valid( classifier ) );
     443            0 :     u8_error_t write_err = U8_ERROR_NONE;
     444            0 :     u8_error_t data_err = U8_ERROR_NONE;
     445              : 
     446              :     /* iterate over all features */
     447              :     data_feature_iterator_t feature_iterator;
     448            0 :     data_err |= data_feature_iterator_init_empty( &feature_iterator );
     449            0 :     data_err |= data_database_reader_get_features_by_classifier_id( (*this_).db_reader,
     450              :                                                                     data_classifier_get_row_id( classifier ),
     451              :                                                                     &feature_iterator
     452              :                                                                   );
     453              : 
     454            0 :     while ( data_feature_iterator_has_next( &feature_iterator ) )
     455              :     {
     456              :         /* get feature */
     457            0 :         data_err |= data_feature_iterator_next( &feature_iterator, &((*this_).temp_from_feature) );
     458            0 :         if ( data_feature_is_valid( &((*this_).temp_from_feature) ) )
     459              :         {
     460            0 :             const bool is_lifeline
     461            0 :                 =( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( &((*this_).temp_from_feature) ) );
     462              : 
     463            0 :             if ( ! is_lifeline )
     464              :             {
     465            0 :                 const data_classifier_type_t classifier_type = data_classifier_get_main_type( classifier );
     466            0 :                 write_err |= io_element_writer_start_feature( (*this_).element_writer, classifier_type,
     467            0 :                                                               &((*this_).temp_from_feature)
     468              :                                                             );
     469            0 :                 write_err |= io_element_writer_assemble_feature( (*this_).element_writer,
     470              :                                                                  classifier,
     471            0 :                                                                  &((*this_).temp_from_feature)
     472              :                                                                );
     473            0 :                 write_err |= io_element_writer_end_feature( (*this_).element_writer,
     474              :                                                             classifier_type,
     475            0 :                                                             &((*this_).temp_from_feature)
     476              :                                                           );
     477              :             }
     478              :             /* else: */
     479              :             /* lifelines are handled in io_export_model_traversal_private_fake_interactions_of_node */
     480              :         }
     481              :         else
     482              :         {
     483            0 :             assert( false );
     484              :         }
     485              :     }
     486            0 :     data_err |= data_feature_iterator_destroy( &feature_iterator );
     487              : 
     488            0 :     U8_TRACE_END_ERR( write_err | data_err );
     489            0 :     return write_err | data_err;
     490              : }
     491              : 
     492            0 : u8_error_t io_export_model_traversal_private_iterate_node_relationships ( io_export_model_traversal_t *this_,
     493              :                                                                           bool nested_to_foreign_node,
     494              :                                                                           const data_classifier_t *host,
     495              :                                                                           const data_classifier_t *classifier )
     496              : {
     497            0 :     U8_TRACE_BEGIN();
     498            0 :     assert( classifier != NULL );
     499            0 :     assert( data_classifier_is_valid( classifier ) );
     500            0 :     u8_error_t write_err = U8_ERROR_NONE;
     501            0 :     u8_error_t data_err = U8_ERROR_NONE;
     502              : 
     503            0 :     const data_classifier_type_t host_type
     504            0 :         = (host==NULL) ? DATA_CLASSIFIER_TYPE_PACKAGE : data_classifier_get_main_type( host );  /* a uml:Model is a uml:Package*/
     505            0 :     const data_id_t classifier_id = data_classifier_get_data_id( classifier );
     506              : 
     507              :     /* iterate over all relationships */
     508              :     data_relationship_iterator_t rel_iterator;
     509            0 :     data_err |= data_relationship_iterator_init_empty( &rel_iterator );
     510            0 :     data_err |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
     511              :                                                                          data_classifier_get_row_id( classifier ),
     512              :                                                                          &rel_iterator
     513              :                                                                        );
     514              : 
     515            0 :     while ( data_relationship_iterator_has_next( &rel_iterator ) )
     516              :     {
     517              :         /* get relationship */
     518            0 :         data_err |= data_relationship_iterator_next( &rel_iterator, &((*this_).temp_relationship) );
     519            0 :         if ( data_relationship_is_valid( &((*this_).temp_relationship) ) )
     520              :         {
     521              :             /* determine if the relationship is a duplicate */
     522            0 :             const data_id_t relation_id = data_relationship_get_data_id( &((*this_).temp_relationship) );
     523            0 :             const bool duplicate_relationship
     524            0 :                 = ( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &relation_id ) );
     525            0 :             if ( ! duplicate_relationship )
     526              :             {
     527            0 :                 const data_id_t from_classifier_id = data_relationship_get_from_classifier_data_id( &((*this_).temp_relationship) );
     528            0 :                 const bool source_already_written
     529            0 :                     = ( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &from_classifier_id ) );
     530            0 :                 const data_id_t to_classifier_id = data_relationship_get_to_classifier_data_id( &((*this_).temp_relationship) );
     531            0 :                 const bool destination_already_written
     532            0 :                     = ( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &to_classifier_id ) );
     533              : 
     534            0 :                 const data_relationship_type_t r_type = data_relationship_get_main_type( &((*this_).temp_relationship) );
     535              :                 const bool is_relationship_compliant_here
     536            0 :                     = io_element_writer_can_classifier_nest_relationship( (*this_).element_writer, host_type, r_type );
     537            0 :                 const data_id_t from_feature_id = data_relationship_get_from_feature_data_id( &((*this_).temp_relationship) );
     538            0 :                 const bool from_here
     539            0 :                     = ( ( ! data_id_is_valid( &from_feature_id ) )
     540            0 :                     && ( data_id_equals( &from_classifier_id, &classifier_id ) ) );
     541              : 
     542              :                 /* nested_to_foreign_node is kind of yellow or even red emergency node:
     543              :                  * source_already_written and possibly destination_already_written must have passed
     544              :                  * to ensure that there is no other solution;
     545              :                  * either (yellow) is_relationship_compliant_here
     546              :                  * or (red) nesting to package shall be true.
     547              :                  */
     548            0 :                 const bool foreign_yellow_ok
     549            0 :                     = nested_to_foreign_node && source_already_written && is_relationship_compliant_here;
     550            0 :                 const bool foreign_red_ok
     551            0 :                     = nested_to_foreign_node && source_already_written && destination_already_written
     552            0 :                     && ( host_type == DATA_CLASSIFIER_TYPE_PACKAGE );
     553              : 
     554              :                 /* in uml, the source is the dependant, the destination has no link to the source
     555              :                  */
     556            0 :                 const bool local_ok = ( ! nested_to_foreign_node ) && is_relationship_compliant_here && from_here;
     557              : 
     558            0 :                 if ( local_ok || foreign_yellow_ok || foreign_red_ok )
     559              :                 {
     560              :                     /* add the relationship to the duplicates list */
     561            0 :                     write_err |= universal_array_list_append( &((*this_).written_id_set), &relation_id );
     562              : 
     563              :                     /* get the element types at both ends of the relationship */
     564            0 :                     data_classifier_init_empty( &((*this_).temp_from_classifier) );
     565            0 :                     data_feature_init_empty( &((*this_).temp_from_feature) );
     566            0 :                     data_classifier_init_empty( &((*this_).temp_to_classifier) );
     567            0 :                     data_feature_init_empty( &((*this_).temp_to_feature) );
     568              : 
     569              :                     const u8_error_t d_err
     570            0 :                         = io_export_model_traversal_private_get_relationship_ends( this_,
     571              :                                                                                    classifier,
     572            0 :                                                                                    &((*this_).temp_relationship),
     573              :                                                                                    &((*this_).temp_from_classifier),
     574              :                                                                                    &((*this_).temp_from_feature),
     575              :                                                                                    &((*this_).temp_to_classifier),
     576              :                                                                                    &((*this_).temp_to_feature)
     577              :                                                                                  );
     578              : 
     579            0 :                     if ( d_err == U8_ERROR_NONE )
     580              :                     {
     581              :                         /* destination classifier found, print the relation */
     582            0 :                         write_err |= io_element_writer_start_relationship( (*this_).element_writer, host_type, &((*this_).temp_relationship) );
     583            0 :                         write_err |= io_element_writer_assemble_relationship( (*this_).element_writer,
     584              :                                                                               host,
     585            0 :                                                                               &((*this_).temp_relationship),
     586            0 :                                                                               &((*this_).temp_from_classifier),
     587            0 :                                                                               &((*this_).temp_from_feature),
     588            0 :                                                                               &((*this_).temp_to_classifier),
     589            0 :                                                                               &((*this_).temp_to_feature)
     590              :                                                                             );
     591            0 :                         write_err |= io_element_writer_end_relationship( (*this_).element_writer, host_type, &((*this_).temp_relationship) );
     592              :                     }
     593              :                     else
     594              :                     {
     595            0 :                         write_err |= d_err;
     596              :                     }
     597              : 
     598            0 :                     data_classifier_destroy( &((*this_).temp_from_classifier) );
     599            0 :                     data_feature_destroy( &((*this_).temp_from_feature) );
     600            0 :                     data_classifier_destroy( &((*this_).temp_to_classifier) );
     601            0 :                     data_feature_destroy( &((*this_).temp_to_feature) );
     602              :                 }
     603              :             }
     604              :         }
     605              :         else
     606              :         {
     607            0 :             assert( false );
     608              :         }
     609              :     }
     610            0 :     data_err |= data_relationship_iterator_destroy( &rel_iterator );
     611              : 
     612            0 :     U8_TRACE_END_ERR( write_err | data_err );
     613            0 :     return write_err | data_err;
     614              : }
     615              : 
     616            0 : u8_error_t io_export_model_traversal_private_get_relationship_ends( io_export_model_traversal_t *this_,
     617              :                                                                     const data_classifier_t *classifier,
     618              :                                                                     const data_relationship_t *relation,
     619              :                                                                     data_classifier_t *out_from_c,
     620              :                                                                     data_feature_t *out_from_f,
     621              :                                                                     data_classifier_t *out_to_c,
     622              :                                                                     data_feature_t *out_to_f )
     623              : {
     624            0 :     U8_TRACE_BEGIN();
     625            0 :     assert( classifier != NULL );
     626            0 :     assert( relation != NULL );
     627            0 :     assert( out_from_c != NULL );
     628            0 :     assert( out_from_f != NULL );
     629            0 :     assert( out_to_c != NULL );
     630            0 :     assert( out_to_f != NULL );
     631            0 :     u8_error_t data_err = U8_ERROR_NONE;
     632              : 
     633              :     {
     634              :         /* get from classifier */
     635            0 :         const data_row_t from_classifier_row_id = data_relationship_get_from_classifier_row_id( relation );
     636            0 :         if ( from_classifier_row_id == data_classifier_get_row_id ( classifier ) )
     637              :         {
     638            0 :             data_classifier_replace( out_from_c, classifier );
     639              :         }
     640              :         else
     641              :         {
     642            0 :             data_err |= data_database_reader_get_classifier_by_id( (*this_).db_reader,
     643              :                                                                    from_classifier_row_id,
     644              :                                                                    out_from_c
     645              :                                                                  );
     646              :         }
     647              : 
     648              :         /* get from feature */
     649            0 :         const data_row_t from_feature_row_id = data_relationship_get_from_feature_row_id( relation );
     650            0 :         if ( from_feature_row_id != DATA_ROW_VOID )
     651              :         {
     652            0 :             data_err |=  data_database_reader_get_feature_by_id( (*this_).db_reader,
     653              :                                                                  from_feature_row_id,
     654              :                                                                  out_from_f
     655              :                                                                );
     656              :         }
     657              :         else
     658              :         {
     659            0 :             data_feature_init_empty( out_from_f );
     660              :         }
     661              : 
     662              :         /* get to classifier */
     663            0 :         const data_row_t to_classifier_row_id = data_relationship_get_to_classifier_row_id( relation );
     664            0 :         if ( to_classifier_row_id == data_classifier_get_row_id ( classifier ) )
     665              :         {
     666            0 :             data_classifier_replace( out_to_c, classifier );
     667              :         }
     668              :         else
     669              :         {
     670            0 :             data_err |= data_database_reader_get_classifier_by_id( (*this_).db_reader,
     671              :                                                                    to_classifier_row_id,
     672              :                                                                    out_to_c
     673              :                                                                  );
     674              :         }
     675              : 
     676              :         /* get to feature */
     677            0 :         const data_row_t to_feature_row_id = data_relationship_get_to_feature_row_id( relation );
     678            0 :         if ( to_feature_row_id != DATA_ROW_VOID )
     679              :         {
     680            0 :             data_err |= data_database_reader_get_feature_by_id( (*this_).db_reader,
     681              :                                                                 to_feature_row_id,
     682              :                                                                 out_to_f
     683              :                                                               );
     684              :         }
     685              :         else
     686              :         {
     687            0 :             data_feature_init_empty( out_to_f );
     688              :         }
     689              :     }
     690              : 
     691            0 :     if ( data_err != U8_ERROR_NONE )
     692              :     {
     693            0 :         U8_LOG_ERROR_INT( "A relationship references classifier(s) and/or feature(s) that do not exist:",
     694              :                           data_relationship_get_row_id ( relation )
     695              :                         );
     696              :     }
     697            0 :     U8_TRACE_END_ERR( data_err );
     698            0 :     return data_err;
     699              : }
     700              : 
     701            0 : u8_error_t io_export_model_traversal_private_fake_interactions_of_node ( io_export_model_traversal_t *this_,
     702              :                                                                          data_classifier_type_t nesting_type,
     703              :                                                                          const data_classifier_t *classifier )
     704              : {
     705            0 :     U8_TRACE_BEGIN();
     706            0 :     assert( classifier != NULL );
     707            0 :     assert( data_classifier_is_valid( classifier ) );
     708            0 :     u8_error_t write_err = U8_ERROR_NONE;
     709            0 :     u8_error_t data_err = U8_ERROR_NONE;
     710              : 
     711            0 :     const data_id_t classifier_id = data_classifier_get_data_id( classifier );
     712              : 
     713              :     /* iterate over all features, search for lifelines */
     714              :     data_feature_iterator_t feature_iterator;
     715            0 :     data_err |= data_feature_iterator_init_empty( &feature_iterator );
     716            0 :     data_err |= data_database_reader_get_features_by_classifier_id( (*this_).db_reader,
     717              :                                                                     data_classifier_get_row_id( classifier ),
     718              :                                                                     &feature_iterator
     719              :                                                                   );
     720              : 
     721            0 :     while ( data_feature_iterator_has_next( &feature_iterator ) )
     722              :     {
     723              :         /* get feature */
     724            0 :         data_err |= data_feature_iterator_next( &feature_iterator, &((*this_).temp_from_feature) );
     725            0 :         if ( data_feature_is_valid( &((*this_).temp_from_feature) ) )
     726              :         {
     727              :             /* determine if the feature is a duplicate */
     728            0 :             const data_id_t feature_id = data_feature_get_data_id( &((*this_).temp_from_feature) );
     729            0 :             const bool duplicate_feature
     730            0 :                 = ( -1 != universal_array_list_get_index_of( &((*this_).written_id_set), &feature_id ) );
     731              : 
     732              :             /* determine if the feature is a lifeline */
     733            0 :             const data_feature_type_t feat_type = data_feature_get_main_type( &((*this_).temp_from_feature) );
     734            0 :             const bool is_lifeline = ( feat_type == DATA_FEATURE_TYPE_LIFELINE );
     735              : 
     736            0 :             if (( ! duplicate_feature )&&( is_lifeline ))  /* just an optimization, checked again by (*this_).interaction_helper */
     737              :             {
     738              :                 static const data_classifier_type_t FAKE_INTERACTION
     739              :                     = DATA_CLASSIFIER_TYPE_CLASS; /* interaction is subclass of class */
     740              :                 const bool is_interaction_compliant_here
     741            0 :                     = io_element_writer_can_classifier_nest_classifier( (*this_).element_writer, nesting_type, FAKE_INTERACTION );
     742              : 
     743            0 :                 if ( is_interaction_compliant_here )
     744              :                 {
     745            0 :                     write_err |= io_export_interaction_traversal_iterate_classifier_occurrences( &((*this_).interaction_helper),
     746              :                                                                                                  nesting_type,
     747              :                                                                                                  classifier_id
     748              :                                                                                                );
     749              :                 }
     750              :             }
     751              :         }
     752              :         else
     753              :         {
     754            0 :             assert( false );
     755              :         }
     756              :     }
     757            0 :     data_err |= data_feature_iterator_destroy( &feature_iterator );
     758              : 
     759            0 :     U8_TRACE_END_ERR( write_err | data_err );
     760            0 :     return write_err | data_err;
     761              : }
     762              : 
     763              : 
     764              : /*
     765              : Copyright 2020-2025 Andreas Warnke
     766              : 
     767              : Licensed under the Apache License, Version 2.0 (the "License");
     768              : you may not use this file except in compliance with the License.
     769              : You may obtain a copy of the License at
     770              : 
     771              :     http://www.apache.org/licenses/LICENSE-2.0
     772              : 
     773              : Unless required by applicable law or agreed to in writing, software
     774              : distributed under the License is distributed on an "AS IS" BASIS,
     775              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     776              : See the License for the specific language governing permissions and
     777              : limitations under the License.
     778              : */
        

Generated by: LCOV version 2.0-1