LCOV - code coverage report
Current view: top level - io/source/json - json_importer.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 87.8 % 197 173
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 8 8

            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 "io_gtk.h"
       9              : #include <stdbool.h>
      10              : 
      11           17 : void json_importer_init( json_importer_t *this_, io_import_elements_t *elements_importer )
      12              : {
      13           17 :     U8_TRACE_BEGIN();
      14           17 :     assert( NULL != elements_importer );
      15              : 
      16           17 :     (*this_).elements_importer = elements_importer;
      17              : 
      18           17 :     data_rules_init ( &((*this_).data_rules) );
      19              : 
      20           17 :     U8_TRACE_END();
      21           17 : }
      22              : 
      23           17 : void json_importer_destroy( json_importer_t *this_ )
      24              : {
      25           17 :     U8_TRACE_BEGIN();
      26           17 :     assert( NULL != (*this_).elements_importer );
      27              : 
      28           17 :     data_rules_destroy ( &((*this_).data_rules) );
      29              : 
      30           17 :     (*this_).elements_importer = NULL;
      31              : 
      32           17 :     U8_TRACE_END();
      33           17 : }
      34              : 
      35           21 : 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           21 :     U8_TRACE_BEGIN();
      40           21 :     assert( NULL != json_text );
      41           21 :     assert( NULL != out_err_info );
      42              : 
      43           21 :     u8_error_t sync_error = U8_ERROR_NONE;
      44              : 
      45           21 :     json_element_reader_init( &((*this_).temp_element_reader), json_text );
      46              : 
      47              :     /* read header */
      48           21 :     if ( U8_ERROR_NONE == sync_error )
      49              :     {
      50           21 :         sync_error = json_element_reader_expect_header( &((*this_).temp_element_reader) );
      51              :     }
      52              : 
      53           21 :     if ( U8_ERROR_NONE == sync_error )
      54              :     {
      55           20 :         sync_error = json_importer_private_import_views( this_ );
      56              :     }
      57              : 
      58           21 :     if ( U8_ERROR_NONE == sync_error )
      59              :     {
      60           18 :         sync_error = json_importer_private_import_nodes( this_ );
      61              :     }
      62              : 
      63           21 :     if ( U8_ERROR_NONE == sync_error )
      64              :     {
      65           17 :         sync_error = json_importer_private_import_edges( this_ );
      66              :     }
      67              : 
      68           21 :     if ( U8_ERROR_NONE == sync_error )
      69              :     {
      70           14 :         sync_error = json_element_reader_expect_footer( &((*this_).temp_element_reader) );
      71              :     }
      72              : 
      73              :     /* report line number of current sync_error */
      74           21 :     const uint32_t current_read_line = json_element_reader_get_read_line ( &((*this_).temp_element_reader) );
      75           21 :     u8_error_info_init_line( out_err_info, sync_error, current_read_line );
      76              : 
      77           21 :     json_element_reader_destroy( &((*this_).temp_element_reader) );
      78              : 
      79           21 :     U8_TRACE_END_ERR( sync_error );
      80           21 :     return sync_error;
      81              : }
      82              : 
      83           20 : u8_error_t json_importer_private_import_views( json_importer_t *this_ )
      84              : {
      85           20 :     U8_TRACE_BEGIN();
      86              : 
      87           20 :     u8_error_t sync_error = U8_ERROR_NONE;
      88              : 
      89           20 :     if ( U8_ERROR_NONE == sync_error )
      90              :     {
      91           20 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
      92              :     }
      93              : 
      94           20 :     if ( U8_ERROR_NONE == sync_error )
      95              :     {
      96              :         data_table_t next_object_type;
      97           20 :         bool set_end = false;  /* end of data set reached or error at parsing */
      98           20 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
      99           50 :         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           20 :     U8_TRACE_END_ERR( sync_error );
     170           20 :     return sync_error;
     171              : }
     172              : 
     173           18 : u8_error_t json_importer_private_import_nodes( json_importer_t *this_ )
     174              : {
     175           18 :     U8_TRACE_BEGIN();
     176              : 
     177           18 :     u8_error_t sync_error = U8_ERROR_NONE;
     178              : 
     179           18 :     if ( U8_ERROR_NONE == sync_error )
     180              :     {
     181           18 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
     182              :     }
     183              : 
     184           18 :     if ( U8_ERROR_NONE == sync_error )
     185              :     {
     186              :         data_table_t next_object_type;
     187           18 :         bool set_end = false;  /* end of data set reached or error at parsing */
     188           18 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     189           50 :         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           18 :     U8_TRACE_END_ERR( sync_error );
     254           18 :     return sync_error;
     255              : }
     256              : 
     257           17 : u8_error_t json_importer_private_import_edges( json_importer_t *this_ )
     258              : {
     259           17 :     U8_TRACE_BEGIN();
     260              : 
     261           17 :     u8_error_t sync_error = U8_ERROR_NONE;
     262              : 
     263           17 :     if ( U8_ERROR_NONE == sync_error )
     264              :     {
     265           17 :         sync_error = json_element_reader_expect_begin_top_array( &((*this_).temp_element_reader) );
     266              :     }
     267              : 
     268           17 :     if ( U8_ERROR_NONE == sync_error )
     269              :     {
     270              :         data_table_t next_object_type;
     271           17 :         bool set_end = false;  /* end of data set reached or error at parsing */
     272           17 :         sync_error = json_element_reader_check_end_top_array( &((*this_).temp_element_reader), &set_end );
     273           47 :         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           17 :     U8_TRACE_END_ERR( sync_error );
     336           17 :     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-2025 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 2.0-1