Line data Source code
1 : /* File: xmi_interaction_writer.c; Copyright and License: see below */
2 :
3 : #include "xmi/xmi_interaction_writer.h"
4 : #include "xmi/xmi_element_info_map.h"
5 : #include "xmi/xmi_element_info.h"
6 : #include "xmi/xmi_element_part.h"
7 : #include "xmi/xmi_xml.h"
8 : #include "utf8stringbuf/utf8string.h"
9 : #include "entity/data_id.h"
10 : #include "entity/data_classifier_type.h"
11 : #include "u8/u8_trace.h"
12 : #include "u8/u8_log.h"
13 : #include <stdio.h>
14 : #include <stdbool.h>
15 : #include <assert.h>
16 :
17 : /* Note: when writing, each method typically starts with writing a newline, it does not end with writing a newline. */
18 :
19 0 : void xmi_interaction_writer_init ( xmi_interaction_writer_t *this_,
20 : data_stat_t *io_export_stat,
21 : io_xml_writer_t *out_writer )
22 : {
23 0 : U8_TRACE_BEGIN();
24 0 : assert( NULL != io_export_stat );
25 0 : assert( NULL != out_writer );
26 :
27 0 : (*this_).mode = XMI_WRITER_PASS_BASE;
28 0 : (*this_).export_stat = io_export_stat;
29 0 : (*this_).xml_writer = out_writer;
30 0 : xmi_type_converter_init( &((*this_).xmi_types) );
31 0 : xmi_atom_writer_init( &((*this_).atom_writer), (*this_).xml_writer );
32 :
33 0 : U8_TRACE_END();
34 0 : }
35 :
36 0 : void xmi_interaction_writer_destroy( xmi_interaction_writer_t *this_ )
37 : {
38 0 : U8_TRACE_BEGIN();
39 :
40 0 : xmi_atom_writer_destroy( &((*this_).atom_writer) );
41 0 : xmi_type_converter_destroy( &((*this_).xmi_types) );
42 0 : (*this_).xml_writer = NULL; /* unreference */
43 0 : (*this_).export_stat = NULL; /* unreference */
44 :
45 0 : U8_TRACE_END();
46 0 : }
47 :
48 : #if 0
49 : u8_error_t xmi_interaction_writer_start_diagram( xmi_interaction_writer_t *this_,
50 : data_classifier_type_t parent_type,
51 : const data_diagram_t *diagram_ptr )
52 : {
53 : U8_TRACE_BEGIN();
54 : assert ( NULL != diagram_ptr );
55 : u8_error_t export_err = U8_ERROR_NONE;
56 :
57 : const char *const diagram_name = data_diagram_get_name_const(diagram_ptr);
58 : const char *const diagram_descr = data_diagram_get_description_const(diagram_ptr);
59 : const size_t diagram_descr_len = utf8string_get_length(diagram_descr);
60 : const data_id_t diagram_id = data_diagram_get_data_id(diagram_ptr);
61 :
62 : if ( (*this_).mode == XMI_WRITER_PASS_BASE )
63 : {
64 : /* determine nesting tag */
65 : const char* nesting_property;
66 : const u8_error_t nesting_err
67 : = xmi_type_converter_get_xmi_nesting_property_of_classifier( &((*this_).xmi_types),
68 : parent_type,
69 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake child type */
70 : &nesting_property
71 : );
72 : if ( nesting_err != 0 )
73 : {
74 : /* The caller requested to write an interaction to an illegal place. */
75 : /* This should not have happened, because latest the model is a valid nesting container */
76 : U8_TRACE_INFO("xmi_element_writer: request to write an interaction to an illegal place!")
77 : assert(false);
78 : /* update export statistics */
79 : data_stat_inc_count ( (*this_).export_stat, DATA_STAT_TABLE_CLASSIFIER, DATA_STAT_SERIES_WARNING );
80 : /* inform the user via an XML comment: */
81 : export_err |= xmi_atom_writer_report_illegal_container( &((*this_).atom_writer),
82 : diagram_id,
83 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake child type */
84 : parent_type
85 : );
86 : /* use a fallback */
87 : nesting_property = XMI_ELEMENT_PART_FALLBACK_NESTING_ELEMENT;
88 : }
89 :
90 : /* write nesting tag */
91 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_NL );
92 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_START_TAG_START );
93 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, nesting_property );
94 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
95 : io_xml_writer_increase_indent ( (*this_).xml_writer );
96 :
97 : /* write type attribute */
98 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_START );
99 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_NS_UML );
100 : /* TODO possibly a uml:Collaboration needs to be placed around the DATA_CLASSIFIER_TYPE_INTERACTION? */
101 : const char* c_type = xmi_type_converter_get_xmi_type_of_classifier ( &((*this_).xmi_types),
102 : parent_type,
103 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake child type */
104 : XMI_SPEC_UML
105 : );
106 : export_err |= io_xml_writer_write_xml_enc ( (*this_).xml_writer, c_type );
107 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_END );
108 :
109 : /* write id attribute */
110 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_START );
111 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), diagram_id );
112 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_END );
113 :
114 : /* write name attribute */
115 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_NAME_START );
116 : export_err |= io_xml_writer_write_xml_enc ( (*this_).xml_writer, diagram_name );
117 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_NAME_END );
118 :
119 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_START_TAG_END );
120 :
121 : /* write real id comment */
122 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_COMMENT_START );
123 : export_err |= io_xml_writer_write_plain_id( (*this_).xml_writer, diagram_id );
124 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_COMMENT_END );
125 :
126 : /* write description */
127 : if ( 0 != diagram_descr_len )
128 : {
129 : export_err |= xmi_atom_writer_write_xmi_comment( &((*this_).atom_writer),
130 : diagram_id,
131 : "specification",
132 : diagram_descr
133 : );
134 : }
135 :
136 : /* update export statistics, report as classifier because DATA_CLASSIFIER_TYPE_INTERACTION is a classifier */
137 : data_stat_inc_count ( (*this_).export_stat, DATA_STAT_TABLE_CLASSIFIER, DATA_STAT_SERIES_EXPORTED );
138 : }
139 :
140 : U8_TRACE_END_ERR( export_err );
141 : return export_err;
142 : }
143 :
144 : u8_error_t xmi_interaction_writer_end_diagram( xmi_interaction_writer_t *this_,
145 : data_classifier_type_t parent_type )
146 : {
147 : U8_TRACE_BEGIN();
148 : u8_error_t export_err = U8_ERROR_NONE;
149 :
150 : if ( (*this_).mode == XMI_WRITER_PASS_BASE )
151 : {
152 : /* determine nesting tag */
153 : const char* nesting_property;
154 : const u8_error_t nesting_err
155 : = xmi_type_converter_get_xmi_nesting_property_of_classifier( &((*this_).xmi_types),
156 : parent_type,
157 : DATA_CLASSIFIER_TYPE_INTERACTION, /* fake child type */
158 : &nesting_property
159 : );
160 : if ( nesting_err != 0 )
161 : {
162 : /* The caller requested to write a classifier to an illegal place */
163 : /* use a fallback */
164 : nesting_property = XMI_ELEMENT_PART_FALLBACK_NESTING_ELEMENT;
165 : }
166 :
167 : /* adjust indentation, write end tag */
168 : io_xml_writer_decrease_indent ( (*this_).xml_writer );
169 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_NL );
170 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_END_TAG_START );
171 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, nesting_property );
172 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_END_TAG_END );
173 : }
174 :
175 : U8_TRACE_END_ERR( export_err );
176 : return export_err;
177 : }
178 : #endif
179 :
180 0 : u8_error_t xmi_interaction_writer_assemble_feature( xmi_interaction_writer_t *this_,
181 : data_id_t reference_id,
182 : data_classifier_type_t parent_type,
183 : const data_feature_t *feature_ptr )
184 : {
185 0 : U8_TRACE_BEGIN();
186 0 : assert ( NULL != feature_ptr );
187 0 : u8_error_t export_err = U8_ERROR_NONE;
188 :
189 0 : const data_id_t feature_id = data_feature_get_data_id( feature_ptr );
190 :
191 0 : if ( (*this_).mode == XMI_WRITER_PASS_BASE )
192 : {
193 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_NL );
194 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_START );
195 0 : export_err |= io_xml_writer_write_xml_enc ( (*this_).xml_writer, "represents" );
196 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
197 :
198 : /* write type attribute */
199 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_START );
200 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_NS_UML );
201 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "Property" );
202 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_END );
203 :
204 : /* write id attribute */
205 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_START );
206 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), feature_id );
207 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "#ref" );
208 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_END );
209 :
210 : /* write lifeline id attribute */
211 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "type=\"" );
212 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), reference_id );
213 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "\" " );
214 :
215 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_END );
216 : }
217 :
218 0 : U8_TRACE_END_ERR( export_err );
219 0 : return export_err;
220 : }
221 :
222 0 : u8_error_t xmi_interaction_writer_assemble_relationship( xmi_interaction_writer_t *this_,
223 : data_id_t interaction_id,
224 : data_classifier_type_t parent_type,
225 : const data_relationship_t *relation_ptr,
226 : data_classifier_type_t from_c_type,
227 : data_feature_type_t from_f_type,
228 : data_classifier_type_t to_c_type,
229 : data_feature_type_t to_f_type )
230 : {
231 0 : U8_TRACE_BEGIN();
232 0 : assert ( NULL != relation_ptr );
233 : /* NULL is allowed here: dest_classifier_ptr */
234 0 : u8_error_t export_err = U8_ERROR_NONE;
235 :
236 0 : const data_id_t relation_id = data_relationship_get_data_id( relation_ptr );
237 0 : const char *const relation_descr = data_relationship_get_description_const( relation_ptr );
238 0 : const size_t relation_descr_len = utf8string_get_length(relation_descr);
239 0 : const data_id_t from_classifier_id = data_relationship_get_from_classifier_data_id( relation_ptr );
240 0 : const data_id_t from_feature_id = data_relationship_get_from_feature_data_id( relation_ptr );
241 0 : const data_id_t to_classifier_id = data_relationship_get_to_classifier_data_id( relation_ptr );
242 0 : const data_id_t to_feature_id = data_relationship_get_to_feature_data_id( relation_ptr );
243 0 : const data_relationship_type_t relation_type = data_relationship_get_main_type( relation_ptr );
244 :
245 0 : if ( (*this_).mode == XMI_WRITER_PASS_BASE )
246 : {
247 0 : if ( 0 != relation_descr_len )
248 : {
249 0 : export_err |= xmi_atom_writer_write_xmi_comment( &((*this_).atom_writer),
250 : relation_id,
251 : "specification",
252 : relation_descr
253 : );
254 : }
255 :
256 : /* source */
257 : /* determine from type tag */
258 : const char* from_type_tag;
259 : const int from_type_err
260 0 : = xmi_type_converter_get_xmi_from_property_of_relationship ( &((*this_).xmi_types),
261 : parent_type,
262 : relation_type,
263 : from_c_type,
264 : from_f_type,
265 : &from_type_tag
266 : );
267 0 : if ( from_type_err != 0 )
268 : {
269 : /* The caller requested to write a relationship of illegal source end type */
270 0 : U8_TRACE_INFO("xmi_interaction_writer: request to write a relationship connecting an illegal source end type!");
271 : /* update export statistics */
272 0 : data_stat_inc_count ( (*this_).export_stat, DATA_STAT_TABLE_RELATIONSHIP, DATA_STAT_SERIES_WARNING );
273 : /* inform the user via an XML comment: */
274 0 : export_err |= xmi_atom_writer_report_illegal_relationship_end ( &((*this_).atom_writer),
275 : relation_id,
276 : relation_type,
277 : parent_type,
278 : true /* = from_end */,
279 : from_c_type,
280 : from_f_type
281 : );
282 : }
283 :
284 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_NL );
285 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_START );
286 0 : export_err |= io_xml_writer_write_xml_enc ( (*this_).xml_writer, from_type_tag );
287 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
288 :
289 : /* write type attribute */
290 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_START );
291 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_NS_UML );
292 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_TYPE_MSG_OCCURRENCE_SPEC );
293 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_END );
294 :
295 : /* write id attribute */
296 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_START );
297 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), relation_id );
298 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_ID_FRAGMENT_SOURCE_END );
299 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_END );
300 :
301 : /* write lifeline id attribute */
302 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_PROPERTY_OCCURRENCE_SPEC_COVERED );
303 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_VALUE_START );
304 0 : if ( data_id_is_valid( &from_feature_id ) )
305 : {
306 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), from_feature_id );
307 : }
308 : else
309 : {
310 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), from_classifier_id );
311 : }
312 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_VALUE_END );
313 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
314 :
315 : /* write lifeline id attribute */
316 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "enclosingInteraction=\"" );
317 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), interaction_id );
318 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "\" " );
319 :
320 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_END );
321 :
322 : /* destination */
323 : /* determine from type tag */
324 : const char* to_type_tag;
325 : const int to_type_err
326 0 : = xmi_type_converter_get_xmi_to_property_of_relationship ( &((*this_).xmi_types),
327 : parent_type,
328 : relation_type,
329 : to_c_type,
330 : to_f_type,
331 : &to_type_tag
332 : );
333 0 : if ( to_type_err != 0 )
334 : {
335 : /* The caller requested to write a relationship of illegal target end type */
336 0 : U8_TRACE_INFO("xmi_interaction_writer: request to write a relationship connecting an illegal target end type!");
337 : /* update export statistics */
338 0 : data_stat_inc_count ( (*this_).export_stat, DATA_STAT_TABLE_RELATIONSHIP, DATA_STAT_SERIES_WARNING );
339 : /* inform the user via an XML comment: */
340 0 : export_err |= xmi_atom_writer_report_illegal_relationship_end ( &((*this_).atom_writer),
341 : relation_id,
342 : relation_type,
343 : parent_type,
344 : false /* = from_end */,
345 : to_c_type,
346 : to_f_type
347 : );
348 : }
349 :
350 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_NL );
351 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_START );
352 0 : export_err |= io_xml_writer_write_xml_enc ( (*this_).xml_writer, to_type_tag );
353 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
354 :
355 : /* write type attribute */
356 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_START );
357 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_NS_UML );
358 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_TYPE_MSG_OCCURRENCE_SPEC );
359 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_TYPE_END );
360 :
361 : /* write id attribute */
362 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_START );
363 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), relation_id );
364 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_ID_FRAGMENT_TARGET_END );
365 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_XML_ATTR_ID_END );
366 :
367 : /* write lifeline id attribute */
368 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, XMI_ELEMENT_PART_PROPERTY_OCCURRENCE_SPEC_COVERED );
369 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_VALUE_START );
370 0 : if ( data_id_is_valid( &to_feature_id ) )
371 : {
372 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), to_feature_id );
373 : }
374 : else
375 : {
376 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), to_classifier_id );
377 : }
378 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_VALUE_END );
379 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_ATTR_SEPARATOR );
380 :
381 : /* write lifeline id attribute */
382 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "enclosingInteraction=\"" );
383 0 : export_err |= xmi_atom_writer_encode_xmi_id( &((*this_).atom_writer), interaction_id );
384 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, "\" " );
385 :
386 0 : export_err |= io_xml_writer_write_plain ( (*this_).xml_writer, IO_XML_WRITER_EMPTY_TAG_END );
387 :
388 : }
389 :
390 0 : U8_TRACE_END_ERR( export_err );
391 0 : return export_err;
392 : }
393 :
394 :
395 : /*
396 : Copyright 2020-2024 Andreas Warnke
397 :
398 : Licensed under the Apache License, Version 2.0 (the "License");
399 : you may not use this file except in compliance with the License.
400 : You may obtain a copy of the License at
401 :
402 : http://www.apache.org/licenses/LICENSE-2.0
403 :
404 : Unless required by applicable law or agreed to in writing, software
405 : distributed under the License is distributed on an "AS IS" BASIS,
406 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
407 : See the License for the specific language governing permissions and
408 : limitations under the License.
409 : */
|