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