LCOV - code coverage report
Current view: top level - io/source/json - json_importer.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 173 197 87.8 %
Date: 2024-10-26 21:44:38 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* File: json_importer.c; Copyright and License: see below */
       2             : 
       3             : #include "json/json_importer.h"
       4             : #include "u8/u8_error.h"
       5             : #include "utf8stringbuf/utf8string.h"
       6             : #include "u8/u8_trace.h"
       7             : #include <assert.h>
       8             : #include <gtk/gtk.h>
       9             : #include <stdbool.h>
      10             : 
      11          16 : void json_importer_init( json_importer_t *this_, io_import_elements_t *elements_importer )
      12             : {
      13          16 :     U8_TRACE_BEGIN();
      14          16 :     assert( NULL != elements_importer );
      15             : 
      16          16 :     (*this_).elements_importer = elements_importer;
      17             : 
      18          16 :     data_rules_init ( &((*this_).data_rules) );
      19             : 
      20          16 :     U8_TRACE_END();
      21          16 : }
      22             : 
      23          16 : void json_importer_destroy( json_importer_t *this_ )
      24             : {
      25          16 :     U8_TRACE_BEGIN();
      26          16 :     assert( NULL != (*this_).elements_importer );
      27             : 
      28          16 :     data_rules_destroy ( &((*this_).data_rules) );
      29             : 
      30          16 :     (*this_).elements_importer = NULL;
      31             : 
      32          16 :     U8_TRACE_END();
      33          16 : }
      34             : 
      35          18 : u8_error_t json_importer_import_stream( json_importer_t *this_,
      36             :                                         universal_input_stream_t *json_text,
      37             :                                         u8_error_info_t *out_err_info )
      38             : {
      39          18 :     U8_TRACE_BEGIN();
      40          18 :     assert( NULL != json_text );
      41          18 :     assert( NULL != out_err_info );
      42             : 
      43          18 :     u8_error_t sync_error = U8_ERROR_NONE;
      44             : 
      45          18 :     json_element_reader_init( &((*this_).temp_element_reader), json_text );
      46             : 
      47             :     /* read header */
      48          18 :     if ( U8_ERROR_NONE == sync_error )
      49             :     {
      50          18 :         sync_error = json_element_reader_expect_header( &((*this_).temp_element_reader) );
      51             :     }
      52             : 
      53          18 :     if ( U8_ERROR_NONE == sync_error )
      54             :     {
      55          17 :         sync_error = json_importer_private_import_views( this_ );
      56             :     }
      57             : 
      58          18 :     if ( U8_ERROR_NONE == sync_error )
      59             :     {
      60          15 :         sync_error = json_importer_private_import_nodes( this_ );
      61             :     }
      62             : 
      63          18 :     if ( U8_ERROR_NONE == sync_error )
      64             :     {
      65          14 :         sync_error = json_importer_private_import_edges( this_ );
      66             :     }
      67             : 
      68          18 :     if ( U8_ERROR_NONE == sync_error )
      69             :     {
      70          11 :         sync_error = json_element_reader_expect_footer( &((*this_).temp_element_reader) );
      71             :     }
      72             : 
      73             :     /* report line number of current sync_error */
      74          18 :     const uint32_t current_read_line = json_element_reader_get_read_line ( &((*this_).temp_element_reader) );
      75          18 :     u8_error_info_init_line( out_err_info, sync_error, current_read_line );
      76             : 
      77          18 :     json_element_reader_destroy( &((*this_).temp_element_reader) );
      78             : 
      79          18 :     U8_TRACE_END_ERR( sync_error );
      80          18 :     return sync_error;
      81             : }
      82             : 
      83          17 : u8_error_t json_importer_private_import_views( json_importer_t *this_ )
      84             : {
      85          17 :     U8_TRACE_BEGIN();
      86             : 
      87          17 :     u8_error_t sync_error = U8_ERROR_NONE;
      88             : 
      89          17 :     if ( U8_ERROR_NONE == sync_error )
      90             :     {
      91          17 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
      92             :     }
      93             : 
      94          17 :     if ( U8_ERROR_NONE == sync_error )
      95             :     {
      96             :         data_table_t next_object_type;
      97          17 :         bool set_end = false;  /* end of data set reached or error at parsing */
      98          17 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
      99          44 :         while (( ! set_end ) && ( sync_error == U8_ERROR_NONE ))
     100             :         {
     101          10 :             sync_error = json_element_reader_expect_begin_type_of_element( &((*this_).temp_element_reader), &next_object_type );
     102          10 :             if ( U8_ERROR_NONE == sync_error )
     103             :             {
     104           9 :                 switch ( next_object_type )
     105             :                 {
     106           0 :                     case DATA_TABLE_VOID:
     107             :                     {
     108             :                         /* we are finished */
     109           0 :                         set_end = true;
     110             :                     }
     111           0 :                     break;
     112             : 
     113           9 :                     case DATA_TABLE_DIAGRAM:
     114             :                     {
     115           9 :                         data_diagram_init_empty( &((*this_).temp_diagram) );
     116             :                         /* parent is the uuid of the parent diagram (if not root) */
     117           9 :                         char diag_parent_buf[DATA_UUID_STRING_SIZE] = "";
     118           9 :                         utf8stringbuf_t diag_parent_uuid = UTF8STRINGBUF(diag_parent_buf);
     119             :                         bool has_diagramelements;
     120           9 :                         sync_error = json_element_reader_get_next_diagram( &((*this_).temp_element_reader),
     121             :                                                                            &((*this_).temp_diagram),
     122             :                                                                            diag_parent_uuid,
     123             :                                                                            &has_diagramelements
     124             :                                                                          );
     125           9 :                         if ( U8_ERROR_NONE == sync_error )
     126             :                         {
     127           8 :                             sync_error = io_import_elements_sync_diagram( (*this_).elements_importer,
     128           8 :                                                                           &((*this_).temp_diagram),
     129           8 :                                                                           utf8stringbuf_get_string( diag_parent_uuid )
     130             :                                                                         );
     131             : 
     132           8 :                             if ( has_diagramelements )
     133             :                             {
     134           7 :                                 if ( U8_ERROR_NONE == sync_error )  /* stop reading in case of error */
     135             :                                 {
     136           7 :                                     const char *const diag_uuid = data_diagram_get_uuid_const( &((*this_).temp_diagram) );
     137           7 :                                     sync_error = json_importer_private_import_diagramelement_array( this_, diag_uuid );
     138             :                                 }
     139           7 :                                 if ( U8_ERROR_NONE == sync_error )  /* stop reading in case of error */
     140             :                                 {
     141           7 :                                     sync_error = json_element_reader_end_unfinished_object( &((*this_).temp_element_reader) );
     142             :                                 }
     143             :                             }
     144             : 
     145           8 :                             data_diagram_destroy( &((*this_).temp_diagram) );
     146             :                         }
     147             :                     }
     148           9 :                     break;
     149             : 
     150           0 :                     default:
     151             :                     {
     152           0 :                         U8_LOG_ERROR( "unexpected token error" );
     153           0 :                         sync_error = U8_ERROR_PARSER_STRUCTURE;
     154             :                     }
     155             :                 }
     156           9 :                 if ( U8_ERROR_NONE == sync_error )
     157             :                 {
     158           8 :                     sync_error = json_element_reader_expect_end_type_of_element( &((*this_).temp_element_reader) );
     159             :                 }
     160             :             }
     161             : 
     162          10 :             if ( U8_ERROR_NONE == sync_error )
     163             :             {
     164           8 :                 sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     165             :             }
     166             :         }
     167             :     }
     168             : 
     169          17 :     U8_TRACE_END_ERR( sync_error );
     170          17 :     return sync_error;
     171             : }
     172             : 
     173          15 : u8_error_t json_importer_private_import_nodes( json_importer_t *this_ )
     174             : {
     175          15 :     U8_TRACE_BEGIN();
     176             : 
     177          15 :     u8_error_t sync_error = U8_ERROR_NONE;
     178             : 
     179          15 :     if ( U8_ERROR_NONE == sync_error )
     180             :     {
     181          15 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
     182             :     }
     183             : 
     184          15 :     if ( U8_ERROR_NONE == sync_error )
     185             :     {
     186             :         data_table_t next_object_type;
     187          15 :         bool set_end = false;  /* end of data set reached or error at parsing */
     188          15 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     189          44 :         while (( ! set_end ) && ( sync_error == U8_ERROR_NONE ))
     190             :         {
     191          14 :             sync_error = json_element_reader_expect_begin_type_of_element( &((*this_).temp_element_reader), &next_object_type );
     192          14 :             if ( U8_ERROR_NONE == sync_error )
     193             :             {
     194          14 :                 switch ( next_object_type )
     195             :                 {
     196           0 :                     case DATA_TABLE_VOID:
     197             :                     {
     198             :                         /* we are finished */
     199           0 :                         set_end = true;
     200             :                     }
     201           0 :                     break;
     202             : 
     203          14 :                     case DATA_TABLE_CLASSIFIER:
     204             :                     {
     205          14 :                         data_classifier_init_empty( &((*this_).temp_classifier) );
     206             :                         bool has_features;
     207          14 :                         sync_error = json_element_reader_get_next_classifier( &((*this_).temp_element_reader),
     208             :                                                                               &((*this_).temp_classifier),
     209             :                                                                               &has_features
     210             :                                                                             );
     211          14 :                         if ( U8_ERROR_NONE == sync_error )
     212             :                         {
     213          14 :                             sync_error = io_import_elements_sync_classifier( (*this_).elements_importer,
     214          14 :                                                                              &((*this_).temp_classifier) );
     215             : 
     216          14 :                             if ( has_features )
     217             :                             {
     218          14 :                                 if ( U8_ERROR_NONE == sync_error )  /* stop reading in case of error */
     219             :                                 {
     220          13 :                                     const char *const class_uuid = data_classifier_get_uuid_const( &((*this_).temp_classifier) );
     221          13 :                                     sync_error = json_importer_private_import_feature_array( this_, class_uuid );
     222             :                                 }
     223          14 :                                 if ( U8_ERROR_NONE == sync_error )  /* stop reading in case of error */
     224             :                                 {
     225          13 :                                     sync_error = json_element_reader_end_unfinished_object( &((*this_).temp_element_reader) );
     226             :                                 }
     227             :                             }
     228             : 
     229          14 :                             data_classifier_destroy( &((*this_).temp_classifier) );
     230             :                         }
     231             :                     }
     232          14 :                     break;
     233             : 
     234           0 :                     default:
     235             :                     {
     236           0 :                         U8_LOG_ERROR( "unexpected token error" );
     237           0 :                         sync_error = U8_ERROR_PARSER_STRUCTURE;
     238             :                     }
     239             :                 }
     240          14 :                 if ( U8_ERROR_NONE == sync_error )
     241             :                 {
     242          13 :                     sync_error = json_element_reader_expect_end_type_of_element( &((*this_).temp_element_reader) );
     243             :                 }
     244             :             }
     245             : 
     246          14 :             if ( U8_ERROR_NONE == sync_error )
     247             :             {
     248          13 :                 sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     249             :             }
     250             :         }
     251             :     }
     252             : 
     253          15 :     U8_TRACE_END_ERR( sync_error );
     254          15 :     return sync_error;
     255             : }
     256             : 
     257          14 : u8_error_t json_importer_private_import_edges( json_importer_t *this_ )
     258             : {
     259          14 :     U8_TRACE_BEGIN();
     260             : 
     261          14 :     u8_error_t sync_error = U8_ERROR_NONE;
     262             : 
     263          14 :     if ( U8_ERROR_NONE == sync_error )
     264             :     {
     265          14 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
     266             :     }
     267             : 
     268          14 :     if ( U8_ERROR_NONE == sync_error )
     269             :     {
     270             :         data_table_t next_object_type;
     271          14 :         bool set_end = false;  /* end of data set reached or error at parsing */
     272          14 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     273          41 :         while (( ! set_end ) && ( sync_error == U8_ERROR_NONE ))
     274             :         {
     275          13 :             sync_error = json_element_reader_expect_begin_type_of_element( &((*this_).temp_element_reader), &next_object_type );
     276          13 :             if ( U8_ERROR_NONE == sync_error )
     277             :             {
     278          13 :                 switch ( next_object_type )
     279             :                 {
     280           0 :                     case DATA_TABLE_VOID:
     281             :                     {
     282             :                         /* we are finished */
     283           0 :                         set_end = true;
     284             :                     }
     285           0 :                     break;
     286             : 
     287          13 :                     case DATA_TABLE_RELATIONSHIP:
     288             :                     {
     289          13 :                         data_relationship_init_empty( &((*this_).temp_relationship) );
     290             :                         /* from_node is the uuid of either the from_classifier or (if defined) the from_feature */
     291          13 :                         char rel_from_node_buf[DATA_UUID_STRING_SIZE] = "";
     292          13 :                         utf8stringbuf_t rel_from_node_uuid = UTF8STRINGBUF(rel_from_node_buf);
     293             :                         /* to_node is the uuid of either the to_classifier or (if defined) the to_feature */
     294          13 :                         char rel_to_node_buf[DATA_UUID_STRING_SIZE] = "";
     295          13 :                         utf8stringbuf_t rel_to_node_uuid = UTF8STRINGBUF(rel_to_node_buf);
     296          13 :                         sync_error = json_element_reader_get_next_relationship( &((*this_).temp_element_reader),
     297             :                                                                                 &((*this_).temp_relationship),
     298             :                                                                                 rel_from_node_uuid,
     299             :                                                                                 rel_to_node_uuid
     300             :                                                                               );
     301             : 
     302          13 :                         if ( U8_ERROR_NONE == sync_error )
     303             :                         {
     304          13 :                             sync_error = io_import_elements_sync_relationship( (*this_).elements_importer,
     305          13 :                                                                                &((*this_).temp_relationship),
     306          13 :                                                                                utf8stringbuf_get_string( rel_from_node_uuid ),
     307          13 :                                                                                utf8stringbuf_get_string( rel_to_node_uuid )
     308             :                                                                              );
     309             : 
     310             :                             /* cleanup */
     311          13 :                             data_relationship_destroy( &((*this_).temp_relationship) );
     312             :                         }
     313             :                     }
     314          13 :                     break;
     315             : 
     316           0 :                     default:
     317             :                     {
     318           0 :                         U8_LOG_ERROR( "unexpected token error" );
     319           0 :                         sync_error = U8_ERROR_PARSER_STRUCTURE;
     320             :                     }
     321             :                 }
     322          13 :                 if ( U8_ERROR_NONE == sync_error )
     323             :                 {
     324          10 :                     sync_error = json_element_reader_expect_end_type_of_element( &((*this_).temp_element_reader) );
     325             :                 }
     326             :             }
     327             : 
     328          13 :             if ( U8_ERROR_NONE == sync_error )
     329             :             {
     330          10 :                 sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     331             :             }
     332             :         }
     333             :     }
     334             : 
     335          14 :     U8_TRACE_END_ERR( sync_error );
     336          14 :     return sync_error;
     337             : }
     338             : 
     339           7 : u8_error_t json_importer_private_import_diagramelement_array( json_importer_t *this_, const char *diagram_uuid )
     340             : {
     341           7 :     U8_TRACE_BEGIN();
     342           7 :     assert ( NULL != diagram_uuid );
     343           7 :     u8_error_t sync_error = U8_ERROR_NONE;
     344             : 
     345           7 :     sync_error = json_element_reader_expect_begin_sub_array( &((*this_).temp_element_reader) );
     346             : 
     347           7 :     bool end_array = false;
     348          21 :     while (( ! end_array )&&( U8_ERROR_NONE == sync_error ))
     349             :     {
     350          14 :         sync_error = json_element_reader_check_end_sub_array( &((*this_).temp_element_reader), &end_array );
     351          14 :         if ( U8_ERROR_NONE == sync_error )
     352             :         {
     353          14 :             if ( ! end_array )
     354             :             {
     355           7 :                 data_diagramelement_init_empty( &((*this_).temp_diagramelement) );
     356             :                 /* node is the uuid of either the classifier or (if defined) the focused_feature */
     357           7 :                 char node_uuid_buf[DATA_UUID_STRING_SIZE] = "";
     358           7 :                 utf8stringbuf_t node_uuid = UTF8STRINGBUF(node_uuid_buf);
     359           7 :                 sync_error |= json_element_reader_get_next_diagramelement( &((*this_).temp_element_reader),
     360             :                                                                            &((*this_).temp_diagramelement),
     361             :                                                                            node_uuid
     362             :                                                                          );
     363           7 :                 if ( U8_ERROR_NONE == sync_error )
     364             :                 {
     365           7 :                     sync_error |= io_import_elements_sync_diagramelement( (*this_).elements_importer,
     366           7 :                                                                           &((*this_).temp_diagramelement),
     367             :                                                                           diagram_uuid,
     368           7 :                                                                           utf8stringbuf_get_string( node_uuid )
     369             :                                                                         );
     370           7 :                     data_diagramelement_destroy( &((*this_).temp_diagramelement) );
     371             :                 }
     372             :                 else
     373             :                 {
     374             :                     /* error, break loop */
     375           0 :                     end_array = true;
     376             :                 }
     377             :             }
     378             :         }
     379             :         else
     380             :         {
     381             :             /* error, break loop */
     382           0 :             sync_error |= U8_ERROR_PARSER_STRUCTURE;
     383           0 :             end_array = true;
     384             :         }
     385             :     }
     386             : 
     387           7 :     U8_TRACE_END_ERR( sync_error );
     388           7 :     return sync_error;
     389             : }
     390             : 
     391          13 : u8_error_t json_importer_private_import_feature_array( json_importer_t *this_, const char *classifier_uuid )
     392             : {
     393          13 :     U8_TRACE_BEGIN();
     394          13 :     assert ( NULL != classifier_uuid );
     395          13 :     u8_error_t sync_error = U8_ERROR_NONE;
     396             : 
     397          13 :     sync_error = json_element_reader_expect_begin_sub_array( &((*this_).temp_element_reader) );
     398             : 
     399          13 :     bool end_array = false;
     400          48 :     while (( ! end_array )&&( U8_ERROR_NONE == sync_error ))
     401             :     {
     402          35 :         sync_error = json_element_reader_check_end_sub_array( &((*this_).temp_element_reader), &end_array );
     403          35 :         if ( U8_ERROR_NONE == sync_error )
     404             :         {
     405          35 :             if ( ! end_array )
     406             :             {
     407          22 :                 data_feature_init_empty( &((*this_).temp_feature) );
     408          22 :                 sync_error |= json_element_reader_get_next_feature( &((*this_).temp_element_reader), &((*this_).temp_feature) );
     409          22 :                 if ( U8_ERROR_NONE == sync_error )
     410             :                 {
     411          44 :                     sync_error |= io_import_elements_sync_feature( (*this_).elements_importer,
     412          22 :                                                                    &((*this_).temp_feature),
     413             :                                                                    classifier_uuid
     414             :                                                                  );
     415          22 :                     data_feature_destroy( &((*this_).temp_feature) );
     416             :                 }
     417             :                 else
     418             :                 {
     419             :                     /* error, break loop */
     420           0 :                     end_array = true;
     421             :                 }
     422             :             }
     423             :         }
     424             :         else
     425             :         {
     426             :             /* error, break loop */
     427           0 :             sync_error |= U8_ERROR_PARSER_STRUCTURE;
     428           0 :             end_array = true;
     429             :         }
     430             :     }
     431             : 
     432          13 :     U8_TRACE_END_ERR( sync_error );
     433          13 :     return sync_error;
     434             : }
     435             : 
     436             : 
     437             : /*
     438             : Copyright 2016-2024 Andreas Warnke
     439             : 
     440             : Licensed under the Apache License, Version 2.0 (the "License");
     441             : you may not use this file except in compliance with the License.
     442             : You may obtain a copy of the License at
     443             : 
     444             :     http://www.apache.org/licenses/LICENSE-2.0
     445             : 
     446             : Unless required by applicable law or agreed to in writing, software
     447             : distributed under the License is distributed on an "AS IS" BASIS,
     448             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     449             : See the License for the specific language governing permissions and
     450             : limitations under the License.
     451             : */

Generated by: LCOV version 1.16