Line data Source code
1 : /* File: io_export_diagram_traversal.c; Copyright and License: see below */
2 :
3 : #include "io_export_diagram_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 2 : void io_export_diagram_traversal_init( io_export_diagram_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 2 : U8_TRACE_BEGIN();
18 2 : assert( NULL != db_reader );
19 2 : assert( NULL != input_data );
20 2 : assert( NULL != io_export_stat );
21 2 : assert( NULL != out_element_writer );
22 :
23 2 : (*this_).db_reader = db_reader;
24 2 : (*this_).input_data = input_data;
25 2 : data_rules_init ( &((*this_).filter_rules) );
26 2 : (*this_).export_stat = io_export_stat;
27 2 : (*this_).element_writer = out_element_writer;
28 :
29 2 : U8_TRACE_END();
30 2 : }
31 :
32 2 : void io_export_diagram_traversal_destroy( io_export_diagram_traversal_t *this_ )
33 : {
34 2 : U8_TRACE_BEGIN();
35 :
36 2 : data_rules_destroy ( &((*this_).filter_rules) );
37 2 : (*this_).input_data = NULL;
38 2 : (*this_).db_reader = NULL;
39 2 : (*this_).export_stat = NULL;
40 2 : (*this_).element_writer = NULL;
41 :
42 2 : U8_TRACE_END();
43 2 : }
44 :
45 0 : u8_error_t io_export_diagram_traversal_begin_and_walk_diagram ( io_export_diagram_traversal_t *this_,
46 : data_id_t diagram_id,
47 : const char *diagram_file_base_name )
48 : {
49 0 : U8_TRACE_BEGIN();
50 0 : assert( data_id_is_valid( &diagram_id ) );
51 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
52 0 : u8_error_t write_err = U8_ERROR_NONE;
53 :
54 : /* load data to be drawn */
55 0 : data_visible_set_init( (*this_).input_data );
56 : const u8_error_t d_err
57 0 : = data_visible_set_load( (*this_).input_data, data_id_get_row_id( &diagram_id ), (*this_).db_reader );
58 0 : if( d_err != U8_ERROR_NONE )
59 : {
60 0 : write_err = -1;
61 0 : assert(false);
62 : }
63 : else
64 : {
65 0 : assert( data_visible_set_is_valid ( (*this_).input_data ) );
66 :
67 : /* write diagram */
68 0 : const data_diagram_t *diag_ptr = data_visible_set_get_diagram_const( (*this_).input_data );
69 0 : assert( diag_ptr != NULL );
70 0 : assert( data_diagram_is_valid( diag_ptr ) );
71 0 : U8_TRACE_INFO_INT("printing diagram with id",data_diagram_get_row_id(diag_ptr));
72 :
73 : /* load parent diagram if there is one */
74 0 : data_diagram_init_empty( &((*this_).temp_parent_diag) );
75 0 : const data_row_t parent_id = data_diagram_get_parent_row_id( diag_ptr );
76 0 : if ( DATA_ROW_VOID != parent_id )
77 : {
78 : const u8_error_t d_err2
79 0 : = data_database_reader_get_diagram_by_id( (*this_).db_reader, parent_id, &((*this_).temp_parent_diag) );
80 0 : if( d_err2 != U8_ERROR_NONE )
81 : {
82 0 : write_err = -1;
83 0 : assert(false);
84 : }
85 : }
86 :
87 0 : write_err |= io_element_writer_start_diagram( (*this_).element_writer, diag_ptr );
88 0 : write_err |= io_element_writer_assemble_diagram( (*this_).element_writer,
89 0 : &((*this_).temp_parent_diag),
90 : diag_ptr,
91 : diagram_file_base_name
92 : );
93 :
94 0 : data_diagram_destroy( &((*this_).temp_parent_diag) );
95 :
96 : /* write all classifiers */
97 0 : write_err |= io_export_diagram_traversal_private_iterate_diagram_classifiers( this_, (*this_).input_data );
98 :
99 : /* write end of diagram-contents, prepare to descend to children */
100 0 : write_err |= io_element_writer_descend_diagram( (*this_).element_writer, diag_ptr );
101 : }
102 :
103 0 : data_visible_set_destroy( (*this_).input_data );
104 :
105 0 : U8_TRACE_END_ERR( write_err );
106 0 : return write_err;
107 : }
108 :
109 0 : u8_error_t io_export_diagram_traversal_end_diagram ( io_export_diagram_traversal_t *this_, data_id_t diagram_id )
110 : {
111 0 : U8_TRACE_BEGIN();
112 0 : assert( data_id_is_valid( &diagram_id ) );
113 0 : assert( data_id_get_table( &diagram_id ) == DATA_TABLE_DIAGRAM );
114 0 : u8_error_t write_err = U8_ERROR_NONE;
115 :
116 : /* load diagram only to be drawn */
117 0 : data_diagram_t *const diagram_ptr = data_visible_set_get_diagram_ptr ( (*this_).input_data );
118 : const u8_error_t d_err
119 0 : = data_database_reader_get_diagram_by_id( (*this_).db_reader, data_id_get_row_id( &diagram_id ), diagram_ptr );
120 0 : if( d_err != U8_ERROR_NONE )
121 : {
122 0 : write_err = -1;
123 0 : assert(false);
124 : }
125 : else
126 : {
127 0 : assert( data_diagram_is_valid( diagram_ptr ) );
128 :
129 : /* write footer */
130 0 : write_err |= io_element_writer_end_diagram( (*this_).element_writer, diagram_ptr );
131 :
132 0 : data_diagram_destroy( diagram_ptr );
133 : }
134 0 : U8_TRACE_END_ERR( write_err );
135 0 : return write_err;
136 : }
137 :
138 0 : u8_error_t io_export_diagram_traversal_private_iterate_diagram_classifiers ( io_export_diagram_traversal_t *this_,
139 : const data_visible_set_t *diagram_data )
140 : {
141 0 : U8_TRACE_BEGIN();
142 0 : assert( diagram_data != NULL );
143 0 : assert( data_visible_set_is_valid( diagram_data ) );
144 0 : u8_error_t write_err = U8_ERROR_NONE;
145 :
146 : /* iterate over all classifiers */
147 : uint32_t count;
148 0 : count = data_visible_set_get_visible_classifier_count ( diagram_data );
149 0 : for ( uint32_t index = 0; index < count; index ++ )
150 : {
151 : /* get classifier */
152 : const data_visible_classifier_t *const visible_classifier
153 0 : = data_visible_set_get_visible_classifier_const ( diagram_data, index );
154 0 : if (( visible_classifier != NULL ) && ( data_visible_classifier_is_valid( visible_classifier ) ))
155 0 : {
156 : const data_classifier_t *classifier
157 0 : = data_visible_classifier_get_classifier_const( visible_classifier );
158 0 : const data_id_t classifier_id = data_classifier_get_data_id( classifier );
159 0 : U8_TRACE_INFO_INT( "printing classifier with id", data_id_get_row_id( &classifier_id ) );
160 :
161 : /* start+assemble classifier */
162 0 : write_err |= io_element_writer_start_classifier( (*this_).element_writer,
163 : DATA_CLASSIFIER_TYPE_VOID, /* no host */
164 : classifier
165 : );
166 :
167 0 : write_err |= io_element_writer_assemble_classifier( (*this_).element_writer,
168 : DATA_CLASSIFIER_TYPE_VOID, /* no host */
169 : classifier
170 : );
171 :
172 : /* print all features of the classifier */
173 0 : write_err |= io_export_diagram_traversal_private_iterate_classifier_features( this_,
174 : diagram_data,
175 : classifier_id
176 : );
177 :
178 : /* end classifier */
179 0 : write_err |= io_element_writer_end_classifier( (*this_).element_writer,
180 : DATA_CLASSIFIER_TYPE_VOID, /* no host */
181 : classifier
182 : );
183 :
184 : /* print all relationships starting from classifier_id */
185 0 : write_err |= io_export_diagram_traversal_private_iterate_classifier_relationships( this_,
186 : diagram_data,
187 : classifier_id
188 : );
189 :
190 : const data_diagramelement_t *diagele
191 0 : = data_visible_classifier_get_diagramelement_const( visible_classifier );
192 0 : const data_id_t diagele_id = data_diagramelement_get_data_id( diagele );
193 0 : const data_diagram_t *const diagram_ptr = data_visible_set_get_diagram_ptr ( (*this_).input_data );
194 0 : const data_row_t focused_feature_id = data_diagramelement_get_focused_feature_row_id( diagele );
195 0 : const data_feature_t *const focused_f_or_null
196 : = ( focused_feature_id == DATA_ROW_VOID )
197 : ? NULL
198 0 : : data_visible_set_get_feature_by_id_const( diagram_data, focused_feature_id );
199 :
200 0 : U8_TRACE_INFO_INT( "printing diagramelement with id", data_id_get_row_id( &diagele_id ) );
201 :
202 : /* start+assemble+end diagramelement */
203 0 : write_err |= io_element_writer_start_diagramelement( (*this_).element_writer,
204 : diagram_ptr,
205 : diagele
206 : );
207 0 : write_err |= io_element_writer_assemble_diagramelement( (*this_).element_writer,
208 : diagram_ptr,
209 : diagele,
210 : classifier,
211 : focused_f_or_null
212 : );
213 0 : write_err |= io_element_writer_end_diagramelement( (*this_).element_writer,
214 : diagram_ptr,
215 : diagele
216 : );
217 : }
218 : else
219 : {
220 0 : assert( false );
221 : }
222 : }
223 :
224 0 : U8_TRACE_END_ERR( write_err );
225 0 : return write_err;
226 : }
227 :
228 0 : u8_error_t io_export_diagram_traversal_private_iterate_classifier_features ( io_export_diagram_traversal_t *this_,
229 : const data_visible_set_t *diagram_data,
230 : data_id_t classifier_id )
231 : {
232 0 : U8_TRACE_BEGIN();
233 0 : assert( diagram_data != NULL );
234 0 : assert( data_visible_set_is_valid( diagram_data ) );
235 0 : assert( DATA_TABLE_CLASSIFIER == data_id_get_table( &classifier_id ) );
236 0 : assert( DATA_ROW_VOID != data_id_get_row_id( &classifier_id) );
237 0 : u8_error_t write_err = U8_ERROR_NONE;
238 :
239 : /* iterate over all features */
240 : uint32_t count;
241 0 : count = data_visible_set_get_feature_count ( diagram_data );
242 0 : for ( uint32_t index = 0; index < count; index ++ )
243 : {
244 : /* get feature */
245 : const data_feature_t *feature;
246 0 : feature = data_visible_set_get_feature_const ( diagram_data, index );
247 0 : if (( feature != NULL ) && ( data_feature_is_valid( feature ) ))
248 0 : {
249 0 : const data_id_t f_classifier_id = data_feature_get_classifier_data_id( feature );
250 0 : if ( data_id_equals( &classifier_id, &f_classifier_id ) )
251 : {
252 0 : const bool is_visible = data_rules_diagram_shows_feature ( &((*this_).filter_rules),
253 : diagram_data,
254 : data_feature_get_row_id( feature )
255 : );
256 0 : const bool is_lifeline
257 0 : =( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( feature ) );
258 :
259 0 : if ( is_visible && ( ! is_lifeline ) )
260 : {
261 : const data_classifier_t *const parent_classifier
262 0 : = data_visible_set_get_classifier_by_id_const( diagram_data, data_id_get_row_id( &classifier_id ));
263 0 : if ( parent_classifier != NULL )
264 : {
265 0 : write_err |= io_element_writer_start_feature( (*this_).element_writer,
266 : data_classifier_get_main_type( parent_classifier ),
267 : feature
268 : );
269 0 : write_err |= io_element_writer_assemble_feature( (*this_).element_writer,
270 : parent_classifier,
271 : feature
272 : );
273 0 : write_err |= io_element_writer_end_feature( (*this_).element_writer,
274 : data_classifier_get_main_type( parent_classifier ),
275 : feature
276 : );
277 : }
278 : else
279 : {
280 0 : assert ( false ); /* is_visible should not be true if parent_classifier == NULL */
281 : }
282 : }
283 : else
284 : {
285 : /* do not export invisible features or lifelines */
286 : }
287 : }
288 : }
289 : else
290 : {
291 0 : assert( false );
292 : }
293 : }
294 :
295 0 : U8_TRACE_END_ERR( write_err );
296 0 : return write_err;
297 : }
298 :
299 0 : u8_error_t io_export_diagram_traversal_private_iterate_classifier_relationships ( io_export_diagram_traversal_t *this_,
300 : const data_visible_set_t *diagram_data,
301 : data_id_t from_classifier_id )
302 : {
303 0 : U8_TRACE_BEGIN();
304 0 : assert( diagram_data != NULL );
305 0 : assert( data_visible_set_is_valid( diagram_data ) );
306 0 : assert( DATA_TABLE_CLASSIFIER == data_id_get_table( &from_classifier_id ) );
307 0 : assert( DATA_ROW_VOID != data_id_get_row_id( &from_classifier_id) );
308 0 : u8_error_t write_err = U8_ERROR_NONE;
309 :
310 : /* iterate over all relationships */
311 : uint32_t count;
312 0 : count = data_visible_set_get_relationship_count ( diagram_data );
313 0 : for ( uint32_t index = 0; index < count; index ++ )
314 : {
315 : /* get relationship */
316 : const data_relationship_t *relation;
317 0 : relation = data_visible_set_get_relationship_const ( diagram_data, index );
318 0 : if (( relation != NULL ) && ( data_relationship_is_valid( relation ) ))
319 0 : {
320 0 : const data_id_t r_from_classifier_id = data_relationship_get_from_classifier_data_id( relation );
321 0 : if ( data_id_equals( &from_classifier_id, &r_from_classifier_id ) )
322 : {
323 0 : const data_id_t relation_id = data_relationship_get_data_id( relation );
324 0 : const bool is_visible = data_rules_diagram_shows_relationship ( &((*this_).filter_rules),
325 : diagram_data,
326 : data_id_get_row_id( &relation_id )
327 : );
328 :
329 0 : if ( is_visible /* no filter for duplicates */ )
330 : {
331 0 : const data_row_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation );
332 : const data_classifier_t *const dest_classifier
333 0 : = data_visible_set_get_classifier_by_id_const ( diagram_data, to_classifier_id );
334 0 : if ( dest_classifier != NULL )
335 : {
336 : /* destination classifier found, print the relation */
337 0 : write_err |= io_element_writer_start_relationship( (*this_).element_writer,
338 : DATA_CLASSIFIER_TYPE_VOID,
339 : relation
340 : );
341 0 : write_err |= io_element_writer_assemble_relationship( (*this_).element_writer,
342 : NULL,
343 : relation,
344 : NULL,
345 : NULL,
346 : dest_classifier,
347 : NULL
348 : );
349 0 : write_err |= io_element_writer_end_relationship( (*this_).element_writer,
350 : DATA_CLASSIFIER_TYPE_VOID,
351 : relation
352 : );
353 : }
354 : else
355 : {
356 0 : assert ( false ); /* is_visible should not be true if dest_classifier == NULL */
357 : }
358 : }
359 : }
360 : }
361 : else
362 : {
363 0 : assert( false );
364 : }
365 : }
366 :
367 0 : U8_TRACE_END_ERR( write_err );
368 0 : return write_err;
369 : }
370 :
371 :
372 : /*
373 : Copyright 2016-2025 Andreas Warnke
374 :
375 : Licensed under the Apache License, Version 2.0 (the "License");
376 : you may not use this file except in compliance with the License.
377 : You may obtain a copy of the License at
378 :
379 : http://www.apache.org/licenses/LICENSE-2.0
380 :
381 : Unless required by applicable law or agreed to in writing, software
382 : distributed under the License is distributed on an "AS IS" BASIS,
383 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
384 : See the License for the specific language governing permissions and
385 : limitations under the License.
386 : */
|