Line data Source code
1 : /* File: data_visible_set.c; Copyright and License: see below */
2 :
3 : #include "set/data_visible_set.h"
4 : #include "data_rules.h"
5 : #include "u8/u8_trace.h"
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <assert.h>
9 :
10 17 : void data_visible_set_init( data_visible_set_t *this_ )
11 : {
12 17 : U8_TRACE_BEGIN();
13 17 : U8_TRACE_INFO_INT( "sizeof(data_visible_set_t):", sizeof(data_visible_set_t) );
14 :
15 17 : data_diagram_init_empty( &((*this_).diagram) );
16 17 : (*this_).visible_classifier_count = 0;
17 17 : (*this_).feature_count = 0;
18 17 : (*this_).relationship_count = 0;
19 :
20 17 : U8_TRACE_END();
21 17 : }
22 :
23 1 : void data_visible_set_reinit( data_visible_set_t *this_ )
24 : {
25 1 : U8_TRACE_BEGIN();
26 :
27 1 : data_diagram_reinit_empty( &((*this_).diagram) );
28 1 : data_visible_set_private_destroy_visible_classifiers( this_ );
29 1 : data_visible_set_private_destroy_features( this_ );
30 1 : data_visible_set_private_destroy_relationships( this_ );
31 :
32 1 : U8_TRACE_END();
33 :
34 1 : }
35 :
36 7 : void data_visible_set_destroy( data_visible_set_t *this_ )
37 : {
38 7 : U8_TRACE_BEGIN();
39 :
40 7 : data_diagram_destroy( &((*this_).diagram) );
41 7 : data_visible_set_private_destroy_visible_classifiers( this_ );
42 7 : data_visible_set_private_destroy_features( this_ );
43 7 : data_visible_set_private_destroy_relationships( this_ );
44 :
45 7 : U8_TRACE_END();
46 7 : }
47 :
48 8 : u8_error_t data_visible_set_load( data_visible_set_t *this_, data_row_t diagram_id, data_database_reader_t *db_reader )
49 : {
50 8 : U8_TRACE_BEGIN();
51 8 : assert( NULL != db_reader );
52 8 : u8_error_t result = U8_ERROR_NONE;
53 :
54 8 : if ( DATA_ROW_VOID == diagram_id )
55 : {
56 : /* re-init */
57 1 : data_diagram_reinit_empty( &((*this_).diagram) );
58 :
59 1 : data_visible_set_private_destroy_visible_classifiers( this_ );
60 1 : data_visible_set_private_destroy_features( this_ );
61 1 : data_visible_set_private_destroy_relationships( this_ );
62 : }
63 : else
64 : {
65 7 : data_diagram_destroy( &((*this_).diagram) );
66 7 : data_visible_set_private_destroy_visible_classifiers( this_ );
67 7 : data_visible_set_private_destroy_features( this_ );
68 7 : data_visible_set_private_destroy_relationships( this_ );
69 :
70 : data_rules_t rules;
71 7 : data_rules_init( &rules );
72 :
73 : /* load diagram */
74 : {
75 : const u8_error_t diag_err
76 7 : = data_database_reader_get_diagram_by_id ( db_reader, diagram_id, &((*this_).diagram) );
77 7 : if ( u8_error_contains( diag_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
78 : {
79 0 : U8_LOG_ERROR( "U8_ERROR_STRING_BUFFER_EXCEEDED at loading a diagram" );
80 : }
81 7 : if ( u8_error_more_than( diag_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
82 : {
83 : /* error at loading */
84 1 : data_diagram_reinit_empty( &((*this_).diagram) );
85 : }
86 7 : result |= diag_err; /* collect error flags */
87 : }
88 :
89 : /* load classifiers */
90 : {
91 7 : u8_error_t c_err = U8_ERROR_NONE;
92 7 : (*this_).visible_classifier_count = 0;
93 : data_visible_classifier_iterator_t visible_classifier_iterator;
94 7 : c_err |= data_visible_classifier_iterator_init_empty( &visible_classifier_iterator );
95 7 : c_err |= data_database_reader_get_visible_classifiers_by_diagram_id( db_reader,
96 : diagram_id,
97 : &visible_classifier_iterator
98 : );
99 193 : while ( data_visible_classifier_iterator_has_next( &visible_classifier_iterator )
100 193 : && ( ! u8_error_more_than( c_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) )
101 : {
102 186 : if ( (*this_).visible_classifier_count < DATA_VISIBLE_SET_MAX_CLASSIFIERS )
103 : {
104 185 : data_visible_classifier_t *const current_visible_classifier
105 185 : = &((*this_).visible_classifiers[(*this_).visible_classifier_count]);
106 185 : c_err |= data_visible_classifier_iterator_next( &visible_classifier_iterator,
107 : current_visible_classifier
108 : );
109 185 : if ( ! u8_error_more_than( c_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
110 : {
111 185 : (*this_).visible_classifier_count ++;
112 : }
113 : }
114 : else
115 : {
116 1 : c_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
117 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading visible classifiers of a diagram" );
118 : }
119 : }
120 7 : c_err |= data_visible_classifier_iterator_destroy( &visible_classifier_iterator );
121 7 : result |= c_err; /* collect error flags */
122 : }
123 :
124 : /* load features */
125 : {
126 7 : u8_error_t f_err = U8_ERROR_NONE;
127 7 : (*this_).feature_count = 0;
128 : data_feature_iterator_t feature_iterator;
129 7 : f_err |= data_feature_iterator_init_empty( &feature_iterator );
130 7 : f_err |= data_database_reader_get_features_by_diagram_id( db_reader,
131 : diagram_id,
132 : &feature_iterator
133 : );
134 271 : while ( data_feature_iterator_has_next( &feature_iterator )
135 271 : && ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) )
136 : {
137 264 : if ( (*this_).feature_count < DATA_VISIBLE_SET_MAX_FEATURES )
138 : {
139 263 : data_feature_t *const current_feature = &((*this_).features[(*this_).feature_count]);
140 263 : f_err |= data_feature_iterator_next( &feature_iterator, current_feature );
141 263 : if ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
142 : {
143 : /* Ignore lifelines (== is_scenario) that do not belong to current diagram */
144 : const bool is_scenario =
145 263 : data_rules_feature_is_scenario_cond( &rules, data_feature_get_main_type( current_feature ) );
146 263 : bool is_foreign_scenario = is_scenario;
147 33045 : for( uint_fast32_t vc_idx = 0; vc_idx < (*this_).visible_classifier_count; vc_idx ++ )
148 : {
149 : const data_diagramelement_t *const diag_ele
150 32782 : = data_visible_classifier_get_diagramelement_const( &((*this_).visible_classifiers[vc_idx]) );
151 32782 : const data_row_t focus_id = data_diagramelement_get_focused_feature_row_id( diag_ele );
152 32782 : if ( data_feature_get_row_id( current_feature ) == focus_id )
153 : {
154 2 : is_foreign_scenario = false;
155 : }
156 : }
157 263 : if ( ! is_foreign_scenario ) /* either not a scenario or a scenario that is in scope of the diagram */
158 : {
159 261 : (*this_).feature_count++;
160 : }
161 : else
162 : {
163 2 : U8_TRACE_INFO_INT( "filtered a foreign scenario lifeline:",
164 : data_feature_get_row_id( current_feature )
165 : );
166 : }
167 : }
168 : }
169 : else
170 : {
171 1 : f_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
172 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading features of a diagram" );
173 : }
174 : }
175 7 : f_err |= data_feature_iterator_destroy( &feature_iterator );
176 7 : result |= f_err; /* collect error flags */
177 : }
178 :
179 : /* load relationships */
180 : {
181 7 : u8_error_t r_err = U8_ERROR_NONE;
182 7 : (*this_).relationship_count = 0;
183 : data_relationship_iterator_t rel_iterator;
184 7 : r_err |= data_relationship_iterator_init_empty( &rel_iterator );
185 7 : r_err |= data_database_reader_get_relationships_by_diagram_id( db_reader,
186 : diagram_id,
187 : &rel_iterator
188 : );
189 402 : while ( data_relationship_iterator_has_next( &rel_iterator )
190 402 : && ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) )
191 : {
192 395 : if ( (*this_).relationship_count < DATA_VISIBLE_SET_MAX_RELATIONSHIPS )
193 : {
194 394 : data_relationship_t *const current_relationship = &((*this_).relationships[(*this_).relationship_count]);
195 394 : r_err |= data_relationship_iterator_next( &rel_iterator, current_relationship );
196 394 : if ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
197 : {
198 : /* Ignore relationships that have not both ends in current diagram - e.g. messages between foreign lifelines */
199 394 : const data_row_t from_feat_row_id = data_relationship_get_from_feature_row_id( current_relationship );
200 394 : const data_row_t to_feat_row_id = data_relationship_get_to_feature_row_id( current_relationship );
201 394 : bool from_known = ( from_feat_row_id == DATA_ROW_VOID );
202 394 : bool to_known = ( to_feat_row_id == DATA_ROW_VOID );
203 98717 : for( uint_fast32_t f_idx = 0; f_idx < (*this_).feature_count; f_idx ++ )
204 : {
205 98323 : const data_feature_t *const probe_feature = &((*this_).features[f_idx]);
206 98323 : const data_row_t probe_feat_id = data_feature_get_row_id( probe_feature );
207 98323 : if ( probe_feat_id == from_feat_row_id )
208 : {
209 4 : from_known = true;
210 : }
211 98323 : if ( probe_feat_id == to_feat_row_id )
212 : {
213 3 : to_known = true;
214 : }
215 : }
216 394 : if ( from_known && to_known ) /* check that both relationship ends are in this data_visible_set_t */
217 : {
218 391 : (*this_).relationship_count++;
219 : }
220 : else
221 : {
222 3 : U8_TRACE_INFO_INT( "filtered a foreign scenario message:",
223 : data_relationship_get_row_id( current_relationship )
224 : );
225 : }
226 : }
227 : }
228 : else
229 : {
230 1 : r_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
231 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading relationships of a diagram" );
232 : }
233 : }
234 7 : r_err |= data_relationship_iterator_destroy( &rel_iterator );
235 7 : result |= r_err; /* collect error flags */
236 : }
237 :
238 7 : data_rules_destroy( &rules );
239 : }
240 :
241 : /* update the containment cache */
242 8 : data_visible_set_update_containment_cache( this_ );
243 :
244 8 : U8_TRACE_END_ERR(result);
245 8 : return result;
246 : }
247 :
248 18 : void data_visible_set_update_containment_cache ( data_visible_set_t *this_ )
249 : {
250 18 : U8_TRACE_BEGIN();
251 18 : assert( (*this_).relationship_count <= DATA_VISIBLE_SET_MAX_RELATIONSHIPS );
252 18 : assert( (*this_).visible_classifier_count <= DATA_VISIBLE_SET_MAX_CLASSIFIERS );
253 :
254 : /* reset the containment array */
255 18 : memset( &((*this_).containment_cache), '\0', sizeof( (*this_).containment_cache ) );
256 :
257 : static const int MAX_SEARCH_PASSES = 4; /* with 4 passes, we can find ancesters and decendants which are related via 2*4=8 links and more */
258 18 : bool new_containments_found = true;
259 :
260 36 : for ( int pass = 0; ( pass < MAX_SEARCH_PASSES ) && new_containments_found; pass ++ )
261 : {
262 18 : new_containments_found = false;
263 :
264 2748 : for ( uint32_t rel_idx = 0; rel_idx < (*this_).relationship_count; rel_idx ++ )
265 : {
266 : data_relationship_t *the_relationship;
267 2730 : the_relationship = &((*this_).relationships[rel_idx]);
268 :
269 : data_relationship_type_t the_type;
270 2730 : the_type = data_relationship_get_main_type ( the_relationship );
271 :
272 2730 : if ( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == the_type )
273 : {
274 : data_row_t parent_id;
275 : data_row_t child_id;
276 385 : parent_id = data_relationship_get_from_classifier_row_id ( the_relationship );
277 385 : child_id = data_relationship_get_to_classifier_row_id ( the_relationship );
278 : int32_t parent_index;
279 : int32_t child_index;
280 385 : parent_index = data_visible_set_get_classifier_index ( this_, parent_id );
281 385 : child_index = data_visible_set_get_classifier_index ( this_, child_id );
282 385 : if ( ( parent_index != -1 )&&( child_index != -1 ) )
283 : {
284 385 : assert ( 0 <= parent_index );
285 385 : assert ( parent_index < (*this_).visible_classifier_count );
286 385 : assert ( 0 <= child_index );
287 385 : assert ( child_index < (*this_).visible_classifier_count );
288 :
289 : /* add the current relation to the containment_cache */
290 385 : (*this_).containment_cache[parent_index][child_index] = true;
291 :
292 : /* all ancestors of parent are ancestors of child */
293 49539 : for ( uint32_t ancestor_index = 0; ancestor_index < (*this_).visible_classifier_count; ancestor_index ++ )
294 : {
295 49154 : if ( (*this_).containment_cache[ancestor_index][parent_index] )
296 : {
297 0 : if ( ! (*this_).containment_cache[ancestor_index][child_index] )
298 : {
299 0 : new_containments_found = true;
300 0 : (*this_).containment_cache[ancestor_index][child_index] = true;
301 : }
302 : }
303 : }
304 :
305 : /* all descendants of child are descendants of parent */
306 49539 : for ( uint32_t descendant_index = 0; descendant_index < (*this_).visible_classifier_count; descendant_index ++ )
307 : {
308 49154 : if ( (*this_).containment_cache[child_index][descendant_index] )
309 : {
310 0 : if ( ! (*this_).containment_cache[parent_index][descendant_index] )
311 : {
312 0 : new_containments_found = true;
313 0 : (*this_).containment_cache[parent_index][descendant_index] = true;
314 : }
315 : }
316 : }
317 :
318 : }
319 : /* else relation points outside the set of classifiers visible in current diagram */
320 : }
321 : }
322 : }
323 :
324 18 : U8_TRACE_END();
325 18 : }
326 :
327 :
328 : /*
329 : Copyright 2016-2025 Andreas Warnke
330 :
331 : Licensed under the Apache License, Version 2.0 (the "License");
332 : you may not use this file except in compliance with the License.
333 : You may obtain a copy of the License at
334 :
335 : http://www.apache.org/licenses/LICENSE-2.0
336 :
337 : Unless required by applicable law or agreed to in writing, software
338 : distributed under the License is distributed on an "AS IS" BASIS,
339 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
340 : See the License for the specific language governing permissions and
341 : limitations under the License.
342 : */
|