Line data Source code
1 : /* File: consistency_drop_invisibles.c; Copyright and License: see below */
2 :
3 : #include "consistency/consistency_drop_invisibles.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 42 : void consistency_drop_invisibles_init( consistency_drop_invisibles_t *this_,
10 : data_database_reader_t *db_reader,
11 : struct ctrl_classifier_controller_struct *clfy_ctrl,
12 : struct ctrl_diagram_controller_struct *diag_ctrl )
13 : {
14 42 : U8_TRACE_BEGIN();
15 42 : assert( NULL != db_reader );
16 42 : assert( NULL != clfy_ctrl );
17 42 : assert( NULL != diag_ctrl );
18 :
19 42 : (*this_).db_reader = db_reader;
20 42 : (*this_).clfy_ctrl = clfy_ctrl;
21 42 : (*this_).diag_ctrl = diag_ctrl;
22 :
23 42 : U8_TRACE_END();
24 42 : }
25 :
26 42 : void consistency_drop_invisibles_destroy( consistency_drop_invisibles_t *this_ )
27 : {
28 42 : U8_TRACE_BEGIN();
29 :
30 42 : (*this_).db_reader = NULL;
31 42 : (*this_).clfy_ctrl = NULL;
32 42 : (*this_).diag_ctrl = NULL;
33 :
34 42 : U8_TRACE_END();
35 42 : }
36 :
37 : /* ================================ NO ABANDONED CLASSIFIERS ================================ */
38 :
39 5 : u8_error_t consistency_drop_invisibles_delete_unreferenced_classifier( consistency_drop_invisibles_t *this_,
40 : const data_diagramelement_t *deleted_diagramelement )
41 : {
42 5 : U8_TRACE_BEGIN();
43 5 : assert( NULL != deleted_diagramelement );
44 5 : u8_error_t result = U8_ERROR_NONE;
45 :
46 : /* try to also delete the classifier, ignore errors because it is ok if the classifier is still referenced */
47 : u8_error_t my_ctrl_result;
48 :
49 5 : my_ctrl_result = ctrl_classifier_controller_delete_classifier( (*this_).clfy_ctrl,
50 : data_diagramelement_get_classifier_row_id( deleted_diagramelement ),
51 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
52 : );
53 :
54 5 : if ( u8_error_contains( my_ctrl_result, U8_ERROR_OBJECT_STILL_REFERENCED ) )
55 : {
56 3 : U8_LOG_EVENT( "The classifier cannot be deleted because it is still referenced." );
57 : }
58 : else
59 : {
60 : /* report this unexpected error */
61 2 : result |= my_ctrl_result;
62 : }
63 :
64 5 : U8_TRACE_END_ERR( result );
65 5 : return result;
66 : }
67 :
68 : /* ================================ NO INVISIBLE RELATIONSHIPS ================================ */
69 :
70 5 : u8_error_t consistency_drop_invisibles_delete_invisible_relationships( consistency_drop_invisibles_t *this_,
71 : const data_diagramelement_t *deleted_diagramelement )
72 : {
73 5 : U8_TRACE_BEGIN();
74 5 : assert( NULL != deleted_diagramelement );
75 5 : u8_error_t result = U8_ERROR_NONE;
76 :
77 5 : data_row_t classifier_id = data_diagramelement_get_classifier_row_id( deleted_diagramelement );
78 : data_small_set_t relations_to_delete;
79 5 : data_small_set_init( &relations_to_delete );
80 :
81 : /* load relationships to be checked */
82 : data_relationship_iterator_t relationship_iterator;
83 5 : result |= data_relationship_iterator_init_empty( &relationship_iterator );
84 5 : result |= data_database_reader_get_relationships_by_classifier_id( (*this_).db_reader,
85 : classifier_id,
86 : &relationship_iterator
87 : );
88 5 : if ( result == U8_ERROR_NONE )
89 : {
90 7 : while( data_relationship_iterator_has_next( &relationship_iterator ) )
91 : {
92 2 : result |= data_relationship_iterator_next( &relationship_iterator, &((*this_).temp_relationship_buf) );
93 :
94 2 : bool visible = true;
95 : const u8_error_t vis_err
96 2 : = consistency_drop_invisibles_private_has_relationship_a_diagram( this_, &((*this_).temp_relationship_buf), &visible );
97 :
98 2 : if ( vis_err == U8_ERROR_NONE )
99 : {
100 2 : if ( ! visible )
101 : {
102 : /* invisible relationship found */
103 : /* this must be copied into a local data set to make this class re-entrant for recursive calls */
104 1 : const data_id_t relation_to_delete = data_relationship_get_data_id( &((*this_).temp_relationship_buf) );
105 1 : result |= data_small_set_add_obj( &relations_to_delete, relation_to_delete );
106 : }
107 : }
108 : else
109 : {
110 0 : result |= vis_err;
111 : }
112 : }
113 : }
114 : else
115 : {
116 0 : U8_LOG_WARNING( "Relationships of the deleted classifier cannot be checked for being superfluous now." );
117 0 : U8_TRACE_INFO_INT( "classifier has unckecked relationships:", classifier_id );
118 : }
119 5 : result |= data_relationship_iterator_destroy( &relationship_iterator );
120 : /* note that relationship_iterator cannot be used here any longer due to re-entrancy by recursion */
121 :
122 : /* delete all found relationship */
123 5 : const uint32_t relations_count = data_small_set_get_count( &relations_to_delete );
124 6 : for ( uint32_t index2 = 0; index2 < relations_count; index2 ++ )
125 : {
126 1 : const data_id_t delete_rel = data_small_set_get_id( &relations_to_delete, index2 );
127 1 : assert( data_id_get_table( &delete_rel ) == DATA_TABLE_RELATIONSHIP );
128 1 : result |= ctrl_classifier_controller_delete_relationship( (*this_).clfy_ctrl,
129 : data_id_get_row_id( &delete_rel ),
130 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND
131 : );
132 : }
133 :
134 5 : data_small_set_destroy( &relations_to_delete );
135 :
136 5 : U8_TRACE_END_ERR( result );
137 5 : return result;
138 : }
139 :
140 2 : u8_error_t consistency_drop_invisibles_private_has_relationship_a_diagram( consistency_drop_invisibles_t *this_,
141 : const data_relationship_t *relation,
142 : bool *out_result )
143 : {
144 2 : U8_TRACE_BEGIN();
145 2 : assert( NULL != relation );
146 2 : assert( NULL != out_result );
147 2 : u8_error_t result = U8_ERROR_NONE;
148 :
149 2 : const data_row_t from_classifier_id = data_relationship_get_from_classifier_row_id( relation );
150 2 : const data_row_t to_classifier_id = data_relationship_get_to_classifier_row_id( relation );
151 :
152 2 : if ( from_classifier_id == to_classifier_id )
153 : {
154 : /* relationship is visible in one diagram because source and destination are identical */
155 0 : *out_result = true;
156 : }
157 : else
158 : {
159 2 : bool same_diag = false;
160 : data_small_set_t from_diagrams;
161 2 : data_small_set_init( &from_diagrams );
162 :
163 : /* load diagramelements that are referenced by the relationships from end */
164 : {
165 : data_diagramelement_iterator_t diagramelement_iterator;
166 2 : result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator );
167 2 : result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
168 : from_classifier_id,
169 : &diagramelement_iterator
170 : );
171 2 : if ( result == U8_ERROR_NONE )
172 : {
173 4 : while ( data_diagramelement_iterator_has_next( &diagramelement_iterator ) )
174 : {
175 2 : result |= data_diagramelement_iterator_next( &diagramelement_iterator, &((*this_).temp_diagelement_buf) );
176 : const data_id_t from_diag_id
177 2 : = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) );
178 : const u8_error_t ins_err
179 2 : = data_small_set_add_obj( &from_diagrams, from_diag_id );
180 2 : if ( ins_err == U8_ERROR_DUPLICATE_ID )
181 : {
182 : /* not an error */
183 : }
184 : else
185 : {
186 2 : result |= ins_err;
187 : }
188 : }
189 : }
190 2 : result |= data_diagramelement_iterator_destroy( &diagramelement_iterator );
191 : }
192 :
193 : /* load diagramelements that are referenced by the relationships to end */
194 : data_diagramelement_iterator_t diagramelement_iterator2;
195 2 : result |= data_diagramelement_iterator_init_empty( &diagramelement_iterator2 );
196 2 : result |= data_database_reader_get_diagramelements_by_classifier_id( (*this_).db_reader,
197 : to_classifier_id,
198 : &diagramelement_iterator2
199 : );
200 :
201 : /* check for same diagram */
202 2 : if ( result == U8_ERROR_NONE )
203 : {
204 5 : while ( data_diagramelement_iterator_has_next( &diagramelement_iterator2 ) )
205 : {
206 3 : result |= data_diagramelement_iterator_next( &diagramelement_iterator2, &((*this_).temp_diagelement_buf) );
207 : const data_id_t to_diag_id
208 3 : = data_diagramelement_get_diagram_data_id ( &((*this_).temp_diagelement_buf) );
209 3 : if ( data_small_set_contains( &from_diagrams, to_diag_id ) )
210 : {
211 1 : same_diag = true;
212 : }
213 : }
214 : }
215 2 : result |= data_diagramelement_iterator_destroy( &diagramelement_iterator2 );
216 2 : data_small_set_destroy( &from_diagrams );
217 :
218 2 : *out_result = same_diag;
219 : }
220 :
221 2 : U8_TRACE_END_ERR( result );
222 2 : return result;
223 : }
224 :
225 :
226 : /*
227 : Copyright 2018-2025 Andreas Warnke
228 :
229 : Licensed under the Apache License, Version 2.0 (the "License");
230 : you may not use this file except in compliance with the License.
231 : You may obtain a copy of the License at
232 :
233 : http://www.apache.org/licenses/LICENSE-2.0
234 :
235 : Unless required by applicable law or agreed to in writing, software
236 : distributed under the License is distributed on an "AS IS" BASIS,
237 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
238 : See the License for the specific language governing permissions and
239 : limitations under the License.
240 : */
|