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

Generated by: LCOV version 1.16