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