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 : */
|