LCOV - code coverage report
Current view: top level - io/source - io_export_model_traversal.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 0 321 0.0 %
Date: 2024-12-21 18:34:41 Functions: 0 12 0.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-2024 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 1.16