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 269 : while ( data_feature_iterator_has_next( &feature_iterator )
135 269 : && ( ! u8_error_more_than( f_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) )
136 : {
137 262 : if ( (*this_).feature_count < DATA_VISIBLE_SET_MAX_FEATURES )
138 : {
139 261 : data_feature_t *const current_feature = &((*this_).features[(*this_).feature_count]);
140 261 : f_err |= data_feature_iterator_next( &feature_iterator, current_feature );
141 261 : 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 : /* NOTE: The iteraltor already filters lifelines that do not belong to the current diagram, see DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_DIAGRAM_ID */
145 : #if 0
146 : const bool is_scenario =
147 : data_rules_feature_is_scenario_cond( &rules, data_feature_get_main_type( current_feature ) );
148 : bool is_foreign_scenario = is_scenario;
149 : for( uint_fast32_t vc_idx = 0; vc_idx < (*this_).visible_classifier_count; vc_idx ++ )
150 : {
151 : const data_diagramelement_t *const diag_ele
152 : = data_visible_classifier_get_diagramelement_const( &((*this_).visible_classifiers[vc_idx]) );
153 : const data_row_t focus_id = data_diagramelement_get_focused_feature_row_id( diag_ele );
154 : if ( data_feature_get_row_id( current_feature ) == focus_id )
155 : {
156 : is_foreign_scenario = false;
157 : }
158 : }
159 : if ( ! is_foreign_scenario ) /* either not a scenario or a scenario that is in scope of the diagram */
160 : {
161 : #endif
162 261 : (*this_).feature_count++;
163 : #if 0
164 : }
165 : else
166 : {
167 : U8_TRACE_INFO_INT( "filtered a foreign scenario lifeline:",
168 : data_feature_get_row_id( current_feature )
169 : );
170 : }
171 : #endif
172 : }
173 : }
174 : else
175 : {
176 1 : f_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
177 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading features of a diagram" );
178 : }
179 : }
180 7 : f_err |= data_feature_iterator_destroy( &feature_iterator );
181 7 : result |= f_err; /* collect error flags */
182 : }
183 :
184 : /* load relationships */
185 : {
186 7 : u8_error_t r_err = U8_ERROR_NONE;
187 7 : (*this_).relationship_count = 0;
188 : data_relationship_iterator_t rel_iterator;
189 7 : r_err |= data_relationship_iterator_init_empty( &rel_iterator );
190 7 : r_err |= data_database_reader_get_relationships_by_diagram_id( db_reader,
191 : diagram_id,
192 : &rel_iterator
193 : );
194 402 : while ( data_relationship_iterator_has_next( &rel_iterator )
195 402 : && ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) ) )
196 : {
197 395 : if ( (*this_).relationship_count < DATA_VISIBLE_SET_MAX_RELATIONSHIPS )
198 : {
199 394 : data_relationship_t *const current_relationship = &((*this_).relationships[(*this_).relationship_count]);
200 394 : r_err |= data_relationship_iterator_next( &rel_iterator, current_relationship );
201 394 : if ( ! u8_error_more_than( r_err, U8_ERROR_STRING_BUFFER_EXCEEDED ) )
202 : {
203 : /* Ignore relationships that have not both ends in current diagram - e.g. messages between foreign lifelines */
204 394 : const data_row_t from_feat_row_id = data_relationship_get_from_feature_row_id( current_relationship );
205 394 : const data_row_t to_feat_row_id = data_relationship_get_to_feature_row_id( current_relationship );
206 394 : bool from_known = ( from_feat_row_id == DATA_ROW_VOID );
207 394 : bool to_known = ( to_feat_row_id == DATA_ROW_VOID );
208 98717 : for( uint_fast32_t f_idx = 0; f_idx < (*this_).feature_count; f_idx ++ )
209 : {
210 98323 : const data_feature_t *const probe_feature = &((*this_).features[f_idx]);
211 98323 : const data_row_t probe_feat_id = data_feature_get_row_id( probe_feature );
212 98323 : if ( probe_feat_id == from_feat_row_id )
213 : {
214 4 : from_known = true;
215 : }
216 98323 : if ( probe_feat_id == to_feat_row_id )
217 : {
218 3 : to_known = true;
219 : }
220 : }
221 394 : if ( from_known && to_known ) /* check that both relationship ends are in this data_visible_set_t */
222 : {
223 391 : (*this_).relationship_count++;
224 : }
225 : else
226 : {
227 3 : U8_TRACE_INFO_INT( "filtered a foreign scenario message:",
228 : data_relationship_get_row_id( current_relationship )
229 : );
230 : }
231 : }
232 : }
233 : else
234 : {
235 1 : r_err |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
236 1 : U8_LOG_ERROR( "U8_ERROR_ARRAY_BUFFER_EXCEEDED at loading relationships of a diagram" );
237 : }
238 : }
239 7 : r_err |= data_relationship_iterator_destroy( &rel_iterator );
240 7 : result |= r_err; /* collect error flags */
241 : }
242 :
243 7 : data_rules_destroy( &rules );
244 : }
245 :
246 : /* update the containment cache */
247 8 : data_visible_set_update_containment_cache( this_ );
248 :
249 8 : U8_TRACE_END_ERR(result);
250 8 : return result;
251 : }
252 :
253 18 : void data_visible_set_update_containment_cache ( data_visible_set_t *this_ )
254 : {
255 18 : U8_TRACE_BEGIN();
256 18 : assert( (*this_).relationship_count <= DATA_VISIBLE_SET_MAX_RELATIONSHIPS );
257 18 : assert( (*this_).visible_classifier_count <= DATA_VISIBLE_SET_MAX_CLASSIFIERS );
258 :
259 : /* reset the containment array */
260 18 : memset( &((*this_).containment_cache), '\0', sizeof( (*this_).containment_cache ) );
261 :
262 : 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 */
263 18 : bool new_containments_found = true;
264 :
265 36 : for ( int pass = 0; ( pass < MAX_SEARCH_PASSES ) && new_containments_found; pass ++ )
266 : {
267 18 : new_containments_found = false;
268 :
269 2748 : for ( uint32_t rel_idx = 0; rel_idx < (*this_).relationship_count; rel_idx ++ )
270 : {
271 : data_relationship_t *the_relationship;
272 2730 : the_relationship = &((*this_).relationships[rel_idx]);
273 :
274 : data_relationship_type_t the_type;
275 2730 : the_type = data_relationship_get_main_type ( the_relationship );
276 :
277 2730 : if ( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == the_type )
278 : {
279 : data_row_t parent_id;
280 : data_row_t child_id;
281 385 : parent_id = data_relationship_get_from_classifier_row_id ( the_relationship );
282 385 : child_id = data_relationship_get_to_classifier_row_id ( the_relationship );
283 : int32_t parent_index;
284 : int32_t child_index;
285 385 : parent_index = data_visible_set_get_classifier_index ( this_, parent_id );
286 385 : child_index = data_visible_set_get_classifier_index ( this_, child_id );
287 385 : if ( ( parent_index != -1 )&&( child_index != -1 ) )
288 : {
289 385 : assert ( 0 <= parent_index );
290 385 : assert ( parent_index < (*this_).visible_classifier_count );
291 385 : assert ( 0 <= child_index );
292 385 : assert ( child_index < (*this_).visible_classifier_count );
293 :
294 : /* add the current relation to the containment_cache */
295 385 : (*this_).containment_cache[parent_index][child_index] = true;
296 :
297 : /* all ancestors of parent are ancestors of child */
298 49539 : for ( uint32_t ancestor_index = 0; ancestor_index < (*this_).visible_classifier_count; ancestor_index ++ )
299 : {
300 49154 : if ( (*this_).containment_cache[ancestor_index][parent_index] )
301 : {
302 0 : if ( ! (*this_).containment_cache[ancestor_index][child_index] )
303 : {
304 0 : new_containments_found = true;
305 0 : (*this_).containment_cache[ancestor_index][child_index] = true;
306 : }
307 : }
308 : }
309 :
310 : /* all descendants of child are descendants of parent */
311 49539 : for ( uint32_t descendant_index = 0; descendant_index < (*this_).visible_classifier_count; descendant_index ++ )
312 : {
313 49154 : if ( (*this_).containment_cache[child_index][descendant_index] )
314 : {
315 0 : if ( ! (*this_).containment_cache[parent_index][descendant_index] )
316 : {
317 0 : new_containments_found = true;
318 0 : (*this_).containment_cache[parent_index][descendant_index] = true;
319 : }
320 : }
321 : }
322 :
323 : }
324 : /* else relation points outside the set of classifiers visible in current diagram */
325 : }
326 : }
327 : }
328 :
329 18 : U8_TRACE_END();
330 18 : }
331 :
332 :
333 : /*
334 : Copyright 2016-2025 Andreas Warnke
335 :
336 : Licensed under the Apache License, Version 2.0 (the "License");
337 : you may not use this file except in compliance with the License.
338 : You may obtain a copy of the License at
339 :
340 : http://www.apache.org/licenses/LICENSE-2.0
341 :
342 : Unless required by applicable law or agreed to in writing, software
343 : distributed under the License is distributed on an "AS IS" BASIS,
344 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
345 : See the License for the specific language governing permissions and
346 : limitations under the License.
347 : */
|