Line data Source code
1 : /* File: consistency_relationship.c; Copyright and License: see below */
2 :
3 : #include "consistency/consistency_relationship.h"
4 : #include "ctrl_classifier_controller.h"
5 : #include "ctrl_diagram_controller.h"
6 : #include "u8/u8_trace.h"
7 : #include "u8/u8_log.h"
8 :
9 47 : void consistency_relationship_init( consistency_relationship_t *this_,
10 : data_database_reader_t *db_reader,
11 : struct ctrl_classifier_controller_struct *clfy_ctrl )
12 : {
13 47 : U8_TRACE_BEGIN();
14 47 : assert( NULL != db_reader );
15 47 : assert( NULL != clfy_ctrl );
16 :
17 47 : (*this_).db_reader = db_reader;
18 47 : (*this_).clfy_ctrl = clfy_ctrl;
19 47 : data_rules_init( &((*this_).rules) );
20 :
21 47 : U8_TRACE_END();
22 47 : }
23 :
24 47 : void consistency_relationship_destroy( consistency_relationship_t *this_ )
25 : {
26 47 : U8_TRACE_BEGIN();
27 :
28 47 : (*this_).db_reader = NULL;
29 47 : (*this_).clfy_ctrl = NULL;
30 47 : data_rules_destroy( &((*this_).rules) );
31 :
32 47 : U8_TRACE_END();
33 47 : }
34 :
35 9 : u8_error_t consistency_relationship_delete_invisibles_in_diagram( consistency_relationship_t *this_,
36 : const data_diagram_t *updated_diagram,
37 : int32_t * out_deleted_relationships )
38 : {
39 9 : U8_TRACE_BEGIN();
40 9 : assert( updated_diagram != NULL );
41 9 : assert( out_deleted_relationships != NULL );
42 9 : u8_error_t result = U8_ERROR_NONE;
43 :
44 9 : const data_diagram_type_t new_diagram_type = data_diagram_get_diagram_type( updated_diagram );
45 9 : const bool new_diagram_shows_rel = data_rules_diagram_shows_uncond_relationships( &((*this_).rules), new_diagram_type );
46 : /*
47 : const bool new_diagram_is_scenario = data_rules_diagram_is_scenario( &((*this_).rules), new_diagram_type );
48 : const bool new_diagram_shows_msg = data_rules_diagram_shows_scenario_relationships( &((*this_).rules), new_diagram_type );
49 : assert( new_diagram_is_scenario == new_diagram_shows_msg );
50 : */
51 :
52 9 : if ( ! new_diagram_shows_rel )
53 : {
54 6 : *out_deleted_relationships = 0;
55 6 : const data_row_t diagram_id = data_diagram_get_row( updated_diagram );
56 : data_diagramelement_iterator_t diagramelement_iterator;
57 6 : data_diagramelement_iterator_init_empty( &diagramelement_iterator );
58 6 : result |= data_database_reader_get_diagramelements_by_diagram_id( (*this_).db_reader,
59 : diagram_id,
60 : &diagramelement_iterator
61 : );
62 6 : if ( result == U8_ERROR_NONE )
63 : {
64 15 : while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
65 : {
66 : data_diagramelement_t diagelement_buf;
67 9 : result |= data_diagramelement_iterator_next( &diagramelement_iterator, &diagelement_buf );
68 9 : const data_row_t classifier_id = data_diagramelement_get_classifier_row( &diagelement_buf );
69 : int32_t deleted_relationships;
70 9 : result |= consistency_relationship_delete_invisibles_at_classifier( this_, classifier_id, &deleted_relationships );
71 9 : *out_deleted_relationships += deleted_relationships;
72 : }
73 : }
74 6 : result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
75 : }
76 : else
77 : {
78 3 : U8_TRACE_INFO("All unconditional relationships are visible, no need to check for invisibility.");
79 3 : *out_deleted_relationships = 0;
80 : }
81 :
82 9 : U8_TRACE_END_ERR( result );
83 9 : return result;
84 : }
85 :
86 37 : u8_error_t consistency_relationship_delete_invisibles_at_classifier( consistency_relationship_t *this_,
87 : data_row_t classifier_id,
88 : int32_t * out_deleted_relationships )
89 : {
90 37 : U8_TRACE_BEGIN();
91 37 : assert( classifier_id != DATA_ROW_VOID );
92 37 : assert( out_deleted_relationships != NULL );
93 37 : *out_deleted_relationships = 0;
94 37 : u8_error_t result = U8_ERROR_NONE;
95 :
96 : data_small_set_t relations_to_delete;
97 37 : data_small_set_init( &relations_to_delete );
98 :
99 : /* load relationships to be checked */
100 : data_relationship_iterator_t relationship_iterator;
101 37 : data_relationship_iterator_init_empty( &relationship_iterator );
102 37 : result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
103 : classifier_id,
104 : &relationship_iterator
105 : );
106 37 : if ( result == U8_ERROR_NONE )
107 : {
108 67 : while( data_relationship_iterator_has_next( &relationship_iterator ) )
109 : {
110 31 : result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship_buf) );
111 :
112 31 : bool visible = true;
113 : const u8_error_t vis_err
114 31 : = consistency_relationship_private_is_shown_by_a_diagram( this_, &((*this_).temp_relationship_buf), &visible );
115 :
116 31 : if ( vis_err == U8_ERROR_NONE )
117 : {
118 31 : if ( ! visible )
119 : {
120 : /* invisible relationship found */
121 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */
122 3 : const data_id_t relation_to_delete = data_relationship_get_data_id( &((*this_).temp_relationship_buf) );
123 3 : result |= data_small_set_add_obj( &relations_to_delete, relation_to_delete );
124 : }
125 : }
126 31 : result |= vis_err;
127 : }
128 : }
129 : else
130 : {
131 1 : U8_LOG_WARNING( "Relationships of the deleted classifier cannot be checked for being superfluous now." );
132 1 : U8_TRACE_INFO_INT( "classifier has unckecked relationships:", classifier_id );
133 : }
134 37 : result |= data_relationship_iterator_destroy( &relationship_iterator );
135 : /* note that relationship_iterator cannot be used here any longer due to re-entrancy by recursion */
136 :
137 : /* delete all found relationship */
138 37 : const uint32_t relations_count = data_small_set_get_count( &relations_to_delete );
139 40 : for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ )
140 : {
141 3 : const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 );
142 3 : assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP );
143 : const u8_error_t del_err
144 3 : = ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl,
145 : data_id_get_row( &delete_rel ),
146 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
147 : );
148 3 : *out_deleted_relationships += ( del_err == U8_ERROR_NONE ) ? 1 : 0;
149 3 : result |= del_err;
150 : }
151 :
152 37 : data_small_set_destroy( &relations_to_delete );
153 :
154 37 : U8_TRACE_END_ERR( result );
155 37 : return result;
156 : }
157 :
158 31 : u8_error_t consistency_relationship_private_is_shown_by_a_diagram( consistency_relationship_t *this_,
159 : const data_relationship_t *relation,
160 : bool *out_result )
161 : {
162 31 : U8_TRACE_BEGIN();
163 31 : assert( NULL != relation );
164 31 : assert( NULL != out_result );
165 31 : u8_error_t result = U8_ERROR_NONE;
166 :
167 31 : const data_row_t relationship_id = data_relationship_get_row( relation );
168 31 : bool a_diagram_shows_uncond_relationship = false; /* tells if a diagram is found where unconditional relationships are visible */
169 31 : bool a_diagram_shows_scenario_relationship = false; /* tells if a diagram is found where scenario relationships are visible */
170 :
171 : {
172 : data_diagram_iterator_t diagram_iterator;
173 31 : data_diagram_iterator_init_empty( &diagram_iterator );
174 :
175 31 : result |= data_database_reader_get_diagrams_by_relationship_id( (*this_).db_reader,
176 : relationship_id,
177 : &diagram_iterator
178 : );
179 :
180 31 : if ( result == U8_ERROR_NONE )
181 : {
182 66 : while ( data_diagram_iterator_has_next( &diagram_iterator ) )
183 : {
184 35 : result |= data_diagram_iterator_next( &diagram_iterator, &((*this_).temp_diagram_buf) );
185 35 : const data_diagram_type_t diagram_type = data_diagram_get_diagram_type( &((*this_).temp_diagram_buf) );
186 35 : a_diagram_shows_uncond_relationship |= data_rules_diagram_shows_uncond_relationships( &((*this_).rules), diagram_type );
187 : /* Note that ..get_diagrams_by_relationship_id() returns scenario-based diagrams only if the relationship is visible there: */
188 35 : a_diagram_shows_scenario_relationship |= data_rules_diagram_shows_scenario_relationships( &((*this_).rules), diagram_type );
189 :
190 : /* Workaround: Box diagrams show containment relationships - this is not yet handled by (*this_).rules */
191 : /* And possibly a problem because the use may change the type and bypass existing database triggers... TODO */
192 35 : const bool keep_containment_at_box_diagram = ( data_relationship_get_main_type( relation ) == DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT )
193 35 : && ( diagram_type == DATA_DIAGRAM_TYPE_BOX_DIAGRAM );
194 35 : a_diagram_shows_uncond_relationship |= keep_containment_at_box_diagram;
195 : }
196 : }
197 :
198 31 : result |= data_diagram_iterator_destroy( &diagram_iterator );
199 : }
200 :
201 31 : *out_result = ( a_diagram_shows_uncond_relationship || a_diagram_shows_scenario_relationship );
202 :
203 31 : U8_TRACE_END_ERR( result );
204 31 : return result;
205 : }
206 :
207 :
208 : /*
209 : Copyright 2018-2026 Andreas Warnke
210 :
211 : Licensed under the Apache License, Version 2.0 (the "License");
212 : you may not use this file except in compliance with the License.
213 : You may obtain a copy of the License at
214 :
215 : http://www.apache.org/licenses/LICENSE-2.0
216 :
217 : Unless required by applicable law or agreed to in writing, software
218 : distributed under the License is distributed on an "AS IS" BASIS,
219 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
220 : See the License for the specific language governing permissions and
221 : limitations under the License.
222 : */
|