Line data Source code
1 : /* File: io_export_interaction_traversal.c; Copyright and License: see below */
2 :
3 : #include "io_export_interaction_traversal.h"
4 : #include "xmi/xmi_element_info.h"
5 : #include "xmi/xmi_element_info_map.h"
6 : #include "u8/u8_trace.h"
7 : #include "entity/data_diagram.h"
8 : #include "entity/data_classifier.h"
9 : #include <stdint.h>
10 : #include <stdio.h>
11 : #include <stdlib.h>
12 :
13 0 : void io_export_interaction_traversal_init( io_export_interaction_traversal_t *this_,
14 : data_database_reader_t *db_reader,
15 : data_visible_set_t *input_data,
16 : universal_array_list_t *io_written_id_set,
17 : data_stat_t *io_export_stat,
18 : io_element_writer_t *out_element_writer )
19 : {
20 0 : U8_TRACE_BEGIN();
21 0 : assert( NULL != db_reader );
22 0 : assert( NULL != input_data );
23 0 : assert( NULL != io_written_id_set );
24 0 : assert( NULL != io_export_stat );
25 0 : assert( NULL != out_element_writer );
26 :
27 0 : (*this_).db_reader = db_reader;
28 0 : (*this_).input_data = input_data;
29 0 : data_rules_init ( &((*this_).filter_rules) );
30 0 : (*this_).written_id_set = io_written_id_set;
31 0 : (*this_).export_stat = io_export_stat;
32 0 : (*this_).element_writer = out_element_writer;
33 :
34 0 : data_classifier_init_empty( &((*this_).fake_interaction_classifier) );
35 0 : data_classifier_set_main_type( &((*this_).fake_interaction_classifier), DATA_CLASSIFIER_TYPE_INTERACTION );
36 0 : data_feature_init_empty( &((*this_).fake_lifeline_feature) );
37 0 : data_feature_set_main_type( &((*this_).fake_lifeline_feature), DATA_FEATURE_TYPE_LIFELINE );
38 :
39 0 : U8_TRACE_END();
40 0 : }
41 :
42 0 : void io_export_interaction_traversal_destroy( io_export_interaction_traversal_t *this_ )
43 : {
44 0 : U8_TRACE_BEGIN();
45 :
46 0 : data_classifier_destroy( &((*this_).fake_interaction_classifier) );
47 0 : data_feature_destroy( &((*this_).fake_lifeline_feature) );
48 0 : data_rules_destroy ( &((*this_).filter_rules) );
49 0 : (*this_).input_data = NULL;
50 0 : (*this_).db_reader = NULL;
51 0 : (*this_).written_id_set = NULL;
52 0 : (*this_).export_stat = NULL;
53 0 : (*this_).element_writer = NULL;
54 :
55 0 : U8_TRACE_END();
56 0 : }
57 :
58 0 : u8_error_t io_export_interaction_traversal_iterate_classifier_occurrences ( io_export_interaction_traversal_t *this_,
59 : data_classifier_type_t nesting_type,
60 : data_id_t classifier_id )
61 : {
62 0 : U8_TRACE_BEGIN();
63 0 : assert( data_id_is_valid( &classifier_id ) );
64 0 : u8_error_t write_err = U8_ERROR_NONE;
65 :
66 : data_small_set_t out_showing_diagram_ids;
67 0 : data_small_set_init( &out_showing_diagram_ids );
68 : {
69 0 : write_err = data_database_reader_get_diagram_ids_by_classifier_id ( (*this_).db_reader,
70 : data_id_get_row_id( &classifier_id ),
71 : &out_showing_diagram_ids
72 : );
73 0 : if( write_err == U8_ERROR_NONE )
74 : {
75 0 : const uint32_t diag_count = data_small_set_get_count( &out_showing_diagram_ids );
76 0 : for ( uint32_t diag_idx = 0; diag_idx < diag_count; diag_idx ++ )
77 : {
78 0 : const data_id_t diag_id = data_small_set_get_id( &out_showing_diagram_ids, diag_idx );
79 :
80 0 : const bool duplicate_diagram
81 0 : =( -1 != universal_array_list_get_index_of( (*this_).written_id_set, &diag_id ) );
82 :
83 0 : if ( ! duplicate_diagram )
84 : {
85 0 : write_err |= io_export_interaction_traversal_private_walk_diagram( this_, nesting_type, diag_id );
86 : }
87 : }
88 : }
89 : else
90 : {
91 0 : assert(false);
92 : }
93 : }
94 0 : data_small_set_destroy( &out_showing_diagram_ids );
95 :
96 0 : U8_TRACE_END_ERR( write_err );
97 0 : return write_err;
98 : }
99 :
100 0 : u8_error_t io_export_interaction_traversal_private_walk_diagram ( io_export_interaction_traversal_t *this_,
101 : data_classifier_type_t nesting_type,
102 : data_id_t diagram_id )
103 : {
104 0 : U8_TRACE_BEGIN();
105 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
106 0 : u8_error_t write_err = U8_ERROR_NONE;
107 :
108 : /* write part for current diagram */
109 0 : if ( data_id_is_valid( &diagram_id ) )
110 : {
111 : /* load data to be drawn */
112 0 : data_visible_set_init( (*this_).input_data );
113 0 : write_err = data_visible_set_load( (*this_).input_data,
114 : data_id_get_row_id( &diagram_id ),
115 : (*this_).db_reader
116 : );
117 0 : if( write_err != U8_ERROR_NONE )
118 : {
119 0 : assert(false);
120 : }
121 0 : assert( data_visible_set_is_valid ( (*this_).input_data ) );
122 :
123 : /* write diagram */
124 0 : const data_diagram_t *diag_ptr = data_visible_set_get_diagram_const( (*this_).input_data );
125 0 : assert( diag_ptr != NULL );
126 0 : assert( data_diagram_is_valid( diag_ptr ) );
127 0 : const data_diagram_type_t diag_type = data_diagram_get_diagram_type( diag_ptr );
128 0 : const bool is_interaction_type
129 : = (( diag_type == DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM )
130 0 : || ( diag_type == DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM )
131 0 : || ( diag_type == DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM )
132 0 : || ( diag_type == DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM ));
133 :
134 0 : if ( is_interaction_type )
135 : {
136 0 : U8_TRACE_INFO_INT("exporting diagram as interaction, id:",data_diagram_get_row_id(diag_ptr));
137 :
138 : /* add this classifier to the already written elements */
139 0 : write_err |= universal_array_list_append( (*this_).written_id_set, &diagram_id );
140 :
141 0 : data_classifier_t *const fake_interaction = &((*this_).fake_interaction_classifier);
142 0 : write_err |= io_export_interaction_traversal_private_fake_interaction( this_,
143 : diag_ptr,
144 : fake_interaction
145 : );
146 :
147 : //write_err |= xmi_interaction_writer_start_diagram( &((*this_).interaction_writer), nesting_type, diag_ptr );
148 0 : write_err |= io_element_writer_start_classifier( (*this_).element_writer, nesting_type, fake_interaction );
149 0 : write_err |= io_element_writer_assemble_classifier( (*this_).element_writer, nesting_type, fake_interaction);
150 :
151 : /* write all classifiers */
152 0 : write_err |= io_export_interaction_traversal_private_iterate_diagram_classifiers( this_,
153 0 : (*this_).input_data,
154 : fake_interaction
155 : );
156 :
157 : //write_err |= xmi_interaction_writer_end_diagram( &((*this_).interaction_writer), nesting_type );
158 0 : write_err |= io_element_writer_end_classifier( (*this_).element_writer, nesting_type, fake_interaction);
159 : }
160 :
161 0 : data_visible_set_destroy( (*this_).input_data );
162 : }
163 :
164 0 : U8_TRACE_END_ERR( write_err );
165 0 : return write_err;
166 : }
167 :
168 0 : u8_error_t io_export_interaction_traversal_private_iterate_diagram_classifiers ( io_export_interaction_traversal_t *this_,
169 : const data_visible_set_t *diagram_data,
170 : const data_classifier_t *fake_interaction )
171 : {
172 0 : U8_TRACE_BEGIN();
173 0 : assert( diagram_data != NULL );
174 0 : assert( data_visible_set_is_valid( diagram_data ) );
175 0 : u8_error_t write_err = U8_ERROR_NONE;
176 :
177 : /* iterate over all classifiers */
178 : uint32_t count;
179 0 : count = data_visible_set_get_visible_classifier_count ( diagram_data );
180 0 : for ( uint32_t index = 0; index < count; index ++ )
181 : {
182 : /* get classifier */
183 : const data_visible_classifier_t *visible_classifier;
184 0 : visible_classifier = data_visible_set_get_visible_classifier_const ( diagram_data, index );
185 0 : if (( visible_classifier != NULL ) && ( data_visible_classifier_is_valid( visible_classifier ) ))
186 0 : {
187 : const data_classifier_t *classifier;
188 0 : classifier = data_visible_classifier_get_classifier_const( visible_classifier );
189 0 : const data_id_t classifier_id = data_classifier_get_data_id(classifier);
190 0 : U8_TRACE_INFO_INT( "printing classifier with id", data_id_get_row_id( &classifier_id ) );
191 : const data_diagramelement_t *diagele;
192 0 : diagele = data_visible_classifier_get_diagramelement_const( visible_classifier );
193 0 : const data_id_t focused_feature_id = data_diagramelement_get_focused_feature_data_id( diagele );
194 :
195 : /* print classifiers if of type comment or interaction-diagram-reference */
196 : {
197 0 : const data_classifier_type_t parent_type = DATA_CLASSIFIER_TYPE_INTERACTION; /* fake parent type */
198 0 : const data_classifier_type_t classifier_type = data_classifier_get_main_type(classifier);
199 0 : const bool is_classifier_compliant_here = io_element_writer_can_classifier_nest_classifier( (*this_).element_writer,
200 : parent_type,
201 : classifier_type
202 : );
203 0 : const bool is_duplicate
204 0 : = ( -1 != universal_array_list_get_index_of( (*this_).written_id_set, &classifier_id ) );
205 0 : if ( is_classifier_compliant_here && ( ! is_duplicate ) )
206 : {
207 : /* add the classifier to the duplicates list */
208 0 : write_err |= universal_array_list_append( (*this_).written_id_set, &classifier_id );
209 :
210 : /* print */
211 0 : write_err |= io_element_writer_start_classifier( (*this_).element_writer, parent_type, classifier );
212 0 : write_err |= io_element_writer_assemble_classifier( (*this_).element_writer, parent_type, classifier );
213 0 : write_err |= io_export_interaction_traversal_private_iterate_node_features( this_,
214 : diagram_data,
215 : classifier
216 : );
217 0 : write_err |= io_element_writer_end_classifier( (*this_).element_writer, parent_type, classifier );
218 : }
219 : }
220 :
221 : /* print focused features (lifelines) of the visible classifier */
222 0 : if ( data_id_is_valid( &focused_feature_id ) )
223 : {
224 0 : write_err |= io_export_interaction_traversal_private_look_for_focused_feature( this_,
225 : diagram_data,
226 : focused_feature_id,
227 : fake_interaction
228 : );
229 :
230 : /* print all relationships starting from focused feature (lifeline) of classifier_id */
231 0 : write_err |= io_export_interaction_traversal_private_iterate_feature_relationships( this_,
232 : diagram_data,
233 : classifier_id,
234 : focused_feature_id,
235 : fake_interaction
236 : );
237 : }
238 : }
239 : else
240 : {
241 0 : assert( false );
242 : }
243 : }
244 :
245 0 : U8_TRACE_END_ERR( write_err );
246 0 : return write_err;
247 : }
248 :
249 0 : u8_error_t io_export_interaction_traversal_private_look_for_focused_feature ( io_export_interaction_traversal_t *this_,
250 : const data_visible_set_t *diagram_data,
251 : data_id_t focused_feature_id,
252 : const data_classifier_t *fake_interaction )
253 : {
254 0 : U8_TRACE_BEGIN();
255 0 : assert( diagram_data != NULL );
256 0 : assert( data_visible_set_is_valid( diagram_data ) );
257 0 : assert( DATA_TABLE_FEATURE == data_id_get_table( &focused_feature_id ) );
258 0 : assert( DATA_ROW_ID_VOID != data_id_get_row_id( &focused_feature_id) );
259 0 : assert( fake_interaction != NULL );
260 0 : u8_error_t write_err = U8_ERROR_NONE;
261 :
262 : /* iterate over all features */
263 : uint32_t count;
264 0 : count = data_visible_set_get_feature_count ( diagram_data );
265 0 : for ( uint32_t index = 0; index < count; index ++ )
266 : {
267 : /* get feature */
268 : const data_feature_t *feature;
269 0 : feature = data_visible_set_get_feature_const ( diagram_data, index );
270 :
271 0 : if (( feature != NULL ) && ( data_feature_is_valid( feature ) ))
272 0 : {
273 0 : const data_id_t feat_id = data_feature_get_data_id( feature );
274 0 : if ( data_id_equals( &focused_feature_id, &feat_id ) )
275 : {
276 0 : const bool is_visible = data_rules_diagram_shows_feature ( &((*this_).filter_rules),
277 : diagram_data,
278 : data_feature_get_row_id( feature )
279 : );
280 0 : const bool is_lifeline
281 0 : =( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( feature ) );
282 :
283 0 : if ( is_visible && is_lifeline )
284 : {
285 : const data_classifier_t *const parent_classifier
286 0 : = data_visible_set_get_classifier_by_id_const( diagram_data, data_feature_get_classifier_row_id( feature ));
287 0 : if ( parent_classifier != NULL )
288 : {
289 : /* add the lifeline to the duplicates list */
290 0 : write_err |= universal_array_list_append( (*this_).written_id_set, &feat_id );
291 :
292 0 : const data_classifier_type_t fake_type = data_classifier_get_main_type( fake_interaction );
293 0 : write_err |= io_element_writer_start_feature( (*this_).element_writer, fake_type, feature );
294 0 : write_err |= io_element_writer_assemble_feature( (*this_).element_writer, fake_interaction, feature );
295 0 : write_err |= io_element_writer_end_feature( (*this_).element_writer, fake_type, feature );
296 : }
297 : else
298 : {
299 0 : assert ( false ); /* is_visible should not be true if parent_classifier == NULL */
300 : }
301 : }
302 : }
303 : }
304 : else
305 : {
306 0 : assert( false );
307 : }
308 : }
309 :
310 0 : U8_TRACE_END_ERR( write_err );
311 0 : return write_err;
312 : }
313 :
314 0 : u8_error_t io_export_interaction_traversal_private_iterate_feature_relationships( io_export_interaction_traversal_t *this_,
315 : const data_visible_set_t *diagram_data,
316 : data_id_t from_classifier_id,
317 : data_id_t focused_feature_id,
318 : const data_classifier_t *fake_interaction )
319 : {
320 0 : U8_TRACE_BEGIN();
321 0 : assert( diagram_data != NULL );
322 0 : assert( data_visible_set_is_valid( diagram_data ) );
323 0 : assert( DATA_TABLE_CLASSIFIER == data_id_get_table( &from_classifier_id ) );
324 0 : assert( DATA_ROW_ID_VOID != data_id_get_row_id( &from_classifier_id) );
325 0 : u8_error_t write_err = U8_ERROR_NONE;
326 :
327 : /* iterate over all relationships */
328 0 : const uint32_t count = data_visible_set_get_relationship_count ( diagram_data );
329 0 : for ( uint32_t index = 0; index < count; index ++ )
330 : {
331 : /* get relationship */
332 : const data_relationship_t *const relation
333 0 : = data_visible_set_get_relationship_const ( diagram_data, index );
334 0 : if (( relation != NULL ) && ( data_relationship_is_valid( relation ) ))
335 0 : {
336 : /*const data_id_t r_from_classifier_id = data_relationship_get_from_classifier_data_id( relation );*/
337 0 : const data_id_t rel_from_feature_id = data_relationship_get_from_feature_data_id( relation );
338 0 : const data_id_t rel_to_feature_id = data_relationship_get_to_feature_data_id( relation );
339 : /*if ( data_id_equals( &from_classifier_id, &r_from_classifier_id ) )*/ /* do not care if send or receive */
340 0 : if (( data_id_equals( &focused_feature_id, &rel_from_feature_id ) )
341 0 : ||( data_id_equals( &focused_feature_id, &rel_to_feature_id ) ))
342 : {
343 0 : const data_id_t relation_id = data_relationship_get_data_id( relation );
344 0 : const bool is_visible = data_rules_diagram_shows_relationship( &((*this_).filter_rules),
345 : diagram_data,
346 : data_id_get_row_id( &relation_id )
347 : );
348 :
349 : const bool is_relationship_compliant_here
350 0 : = io_element_writer_can_classifier_nest_relationship( (*this_).element_writer,
351 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake parent type */
352 : data_relationship_get_main_type( relation )
353 : );
354 :
355 0 : const bool duplicate_relationship
356 0 : = ( -1 != universal_array_list_get_index_of( (*this_).written_id_set, &relation_id ) );
357 :
358 : /* is message */
359 : #if 0
360 : const data_relationship_type_t relation_type = data_relationship_get_main_type( relation );
361 : const xmi_element_info_t *relation_info;
362 : u8_error_t map_err = xmi_element_info_map_get_relationship( &xmi_element_info_map_standard,
363 : false, /* interaction context, not state */
364 : relation_type,
365 : &relation_info
366 : );
367 : if ( map_err != 0 )
368 : {
369 : U8_LOG_WARNING_INT("xmi_element_info_map_get_relationship could not map type", relation_type );
370 : }
371 : #endif
372 :
373 0 : if ( is_visible && ( ! duplicate_relationship ) && is_relationship_compliant_here )
374 : {
375 : /* add the relationship to the duplicates list */
376 0 : write_err |= universal_array_list_append( (*this_).written_id_set, &relation_id );
377 :
378 : /* destination classifier found, print the relation */
379 0 : write_err |= io_element_writer_start_relationship( (*this_).element_writer,
380 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake parent type */
381 : relation
382 : );
383 0 : write_err |= io_element_writer_assemble_relationship( (*this_).element_writer,
384 : fake_interaction,
385 : relation,
386 0 : &((*this_).fake_interaction_classifier), /* fake from classifier type */
387 0 : &((*this_).fake_lifeline_feature), /* guess from feature type */
388 0 : &((*this_).fake_interaction_classifier), /* fake to classifier type */
389 0 : &((*this_).fake_lifeline_feature) /* guess to feature type */
390 : );
391 0 : write_err |= io_element_writer_end_relationship( (*this_).element_writer,
392 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake parent type */
393 : relation
394 : );
395 : }
396 : }
397 : }
398 : else
399 : {
400 0 : assert( false );
401 : }
402 : }
403 :
404 0 : U8_TRACE_END_ERR( write_err );
405 0 : return write_err;
406 : }
407 :
408 0 : u8_error_t io_export_interaction_traversal_private_fake_interaction( io_export_interaction_traversal_t *this_,
409 : const data_diagram_t *interaction_diagram,
410 : data_classifier_t *out_fake_classifier )
411 : {
412 0 : U8_TRACE_BEGIN();
413 0 : assert( out_fake_classifier != NULL );
414 0 : assert( interaction_diagram != NULL );
415 0 : assert( data_diagram_is_valid( interaction_diagram ) );
416 0 : u8_error_t write_err = U8_ERROR_NONE;
417 :
418 0 : data_classifier_set_row_id( out_fake_classifier, 1000000 + data_diagram_get_row_id( interaction_diagram ) );
419 0 : data_classifier_set_main_type( out_fake_classifier, DATA_CLASSIFIER_TYPE_INTERACTION );
420 0 : write_err |= data_classifier_set_stereotype( out_fake_classifier, "" );
421 0 : write_err |= data_classifier_set_name( out_fake_classifier, data_diagram_get_name_const( interaction_diagram ) );
422 0 : write_err |= data_classifier_set_description( out_fake_classifier, data_diagram_get_description_const( interaction_diagram ) );
423 0 : data_classifier_set_x_order( out_fake_classifier, data_diagram_get_list_order( interaction_diagram ) );
424 0 : data_classifier_set_y_order( out_fake_classifier, data_diagram_get_list_order( interaction_diagram ) );
425 0 : data_classifier_set_list_order( out_fake_classifier, data_diagram_get_list_order( interaction_diagram ) );
426 0 : write_err |= data_classifier_set_uuid( out_fake_classifier, data_diagram_get_uuid_const( interaction_diagram ) );
427 :
428 0 : U8_TRACE_END_ERR( write_err );
429 0 : return write_err;
430 : }
431 :
432 0 : u8_error_t io_export_interaction_traversal_private_iterate_node_features( io_export_interaction_traversal_t *this_,
433 : const data_visible_set_t *diagram_data,
434 : const data_classifier_t *parent_classifier )
435 : {
436 0 : U8_TRACE_BEGIN();
437 0 : assert( diagram_data != NULL );
438 0 : assert( data_visible_set_is_valid( diagram_data ) );
439 0 : assert( parent_classifier != NULL );
440 0 : u8_error_t write_err = U8_ERROR_NONE;
441 :
442 : /* get parent classifier if */
443 0 : const data_row_id_t classifier_id = data_classifier_get_row_id( parent_classifier );
444 :
445 : /* iterate over all features */
446 0 : const uint32_t count = data_visible_set_get_feature_count ( diagram_data );
447 0 : for ( uint32_t index = 0; index < count; index ++ )
448 : {
449 : /* get feature */
450 : const data_feature_t *const feature
451 0 : = data_visible_set_get_feature_const ( diagram_data, index );
452 0 : if (( feature != NULL ) && ( data_feature_is_valid( feature ) ))
453 0 : {
454 0 : const bool is_lifeline
455 0 : =( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( feature ) );
456 0 : const bool is_child
457 0 : =( classifier_id == data_feature_get_classifier_row_id( feature ) );
458 :
459 0 : if (( ! is_lifeline )&&( is_child ))
460 : {
461 0 : const data_classifier_type_t classifier_type = data_classifier_get_main_type( parent_classifier );
462 0 : write_err |= io_element_writer_start_feature( (*this_).element_writer, classifier_type, feature );
463 0 : write_err |= io_element_writer_assemble_feature( (*this_).element_writer, parent_classifier, feature );
464 0 : write_err |= io_element_writer_end_feature( (*this_).element_writer, classifier_type, feature );
465 : }
466 : /* else: */
467 : /* lifelines are handled in io_export_interaction_traversal_private_look_for_focused_feature */
468 : }
469 : else
470 : {
471 0 : assert( false );
472 : }
473 : }
474 :
475 0 : U8_TRACE_END_ERR( write_err );
476 0 : return write_err;
477 : }
478 :
479 :
480 : /*
481 : Copyright 2020-2024 Andreas Warnke
482 :
483 : Licensed under the Apache License, Version 2.0 (the "License");
484 : you may not use this file except in compliance with the License.
485 : You may obtain a copy of the License at
486 :
487 : http://www.apache.org/licenses/LICENSE-2.0
488 :
489 : Unless required by applicable law or agreed to in writing, software
490 : distributed under the License is distributed on an "AS IS" BASIS,
491 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
492 : See the License for the specific language governing permissions and
493 : limitations under the License.
494 : */
|