1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * umloperation.c : refactored from uml.c, class.c to final use StdProps
5 * PROP_TYPE_DARRAY, a list where each element is a set
6 * of properies described by the same StdPropDesc
7 * Copyright (C) 2005 Hans Breuer
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 classType = dia.get_object_type ("UML - Class")
27 operType = dia.get_object_type ("UML - Operation")
28 paramType = dia.get_object_type ("UML - Parameter")
30 klass, h1, h2 = classType.create (0,0) # p.x, p.y
31 for f in theFunctions :
32 oper, _h1, _h2 = operType.create (0,0)
33 oper.properties["name"] = f.name
34 oper.properties["type"] = f.type
36 for p in f.parameters :
37 param, _h1, _h2 = paramType.create(0,0)
38 param.properties["name"] = p.name
39 param.properties["type"] = p.type
41 oper.insert(param, -1)
42 klass.insert(oper, -1)
43 layer.add_object(klass)
55 #include "properties.h"
57 extern PropEnumData _uml_visibilities
[];
58 extern PropEnumData _uml_inheritances
[];
60 static PropDescription umloperation_props
[] = {
61 { "name", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
62 N_("Name"), NULL
, NULL
},
63 { "type", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
64 N_("Type"), NULL
, NULL
},
65 { "comment", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
66 N_("Comment"), NULL
, NULL
},
67 { "stereotype", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
68 N_("Stereotype"), NULL
, NULL
},
69 /* visibility: public, protected, private (other languages?) */
70 { "visibility", PROP_TYPE_ENUM
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
71 N_("Visibility"), NULL
, _uml_visibilities
},
72 { "inheritance_type", PROP_TYPE_ENUM
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
73 N_("Inheritance type"), NULL
, _uml_inheritances
},
74 { "query", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
75 N_("Query (const)"), NULL
, NULL
},
76 { "class_scope", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
77 N_("Class scope (static)"), NULL
, NULL
},
78 { "parameters", PROP_TYPE_DARRAY
, PROP_FLAG_VISIBLE
| PROP_FLAG_OPTIONAL
,
79 N_("Parameters"), NULL
, NULL
},
84 static PropOffset umloperation_offsets
[] = {
85 { "name", PROP_TYPE_STRING
, offsetof(UMLOperation
, name
) },
86 { "type", PROP_TYPE_STRING
, offsetof(UMLOperation
, type
) },
87 { "comment", PROP_TYPE_STRING
, offsetof(UMLOperation
, comment
) },
88 { "stereotype", PROP_TYPE_STRING
, offsetof(UMLOperation
, stereotype
) },
89 { "visibility", PROP_TYPE_ENUM
, offsetof(UMLOperation
, visibility
) },
90 { "inheritance_type", PROP_TYPE_ENUM
, offsetof(UMLOperation
, inheritance_type
) },
91 { "class_scope", PROP_TYPE_BOOL
, offsetof(UMLOperation
, class_scope
) },
92 { "parameters", PROP_TYPE_DARRAY
, offsetof(UMLOperation
, parameters
) },
96 PropDescDArrayExtra umloperation_extra
= {
97 { umloperation_props
, umloperation_offsets
, "umloperation" },
98 (NewRecordFunc
)uml_operation_new
,
99 (FreeRecordFunc
)uml_operation_destroy
103 uml_operation_new(void)
106 static gint next_id
= 1;
108 op
= g_new0(UMLOperation
, 1);
109 op
->internal_id
= next_id
++;
110 op
->name
= g_strdup("");
111 op
->comment
= g_strdup("");
112 op
->visibility
= UML_PUBLIC
;
113 op
->inheritance_type
= UML_LEAF
;
115 #if 0 /* setup elsewhere */
116 op
->left_connection
= g_new0(ConnectionPoint
, 1);
117 op
->right_connection
= g_new0(ConnectionPoint
, 1);
123 uml_operation_copy_into(UMLOperation
*srcop
, UMLOperation
*destop
)
126 UMLParameter
*newparam
;
129 destop
->internal_id
= srcop
->internal_id
;
131 if (destop
->name
!= NULL
) {
132 g_free(destop
->name
);
134 destop
->name
= g_strdup(srcop
->name
);
136 if (destop
->type
!= NULL
) {
137 g_free(destop
->type
);
139 if (srcop
->type
!= NULL
) {
140 destop
->type
= g_strdup(srcop
->type
);
145 if (destop
->stereotype
!= NULL
) {
146 g_free(destop
->stereotype
);
148 if(srcop
->stereotype
!= NULL
) {
149 destop
->stereotype
= g_strdup(srcop
->stereotype
);
151 destop
->stereotype
= NULL
;
154 if (destop
->comment
!= NULL
) {
155 g_free(destop
->comment
);
157 if (srcop
->comment
!= NULL
) {
158 destop
->comment
= g_strdup(srcop
->comment
);
160 destop
->comment
= NULL
;
163 destop
->visibility
= srcop
->visibility
;
164 destop
->class_scope
= srcop
->class_scope
;
165 destop
->inheritance_type
= srcop
->inheritance_type
;
166 destop
->query
= srcop
->query
;
168 list
= destop
->parameters
;
169 while (list
!= NULL
) {
170 param
= (UMLParameter
*)list
->data
;
171 uml_parameter_destroy(param
);
172 list
= g_list_next(list
);
174 destop
->parameters
= NULL
;
175 list
= srcop
->parameters
;
176 while (list
!= NULL
) {
177 param
= (UMLParameter
*)list
->data
;
179 newparam
= g_new0(UMLParameter
, 1);
180 newparam
->name
= g_strdup(param
->name
);
181 newparam
->type
= g_strdup(param
->type
);
182 newparam
->comment
= g_strdup(param
->comment
);
184 if (param
->value
!= NULL
)
185 newparam
->value
= g_strdup(param
->value
);
187 newparam
->value
= NULL
;
188 newparam
->kind
= param
->kind
;
190 destop
->parameters
= g_list_append(destop
->parameters
, newparam
);
192 list
= g_list_next(list
);
197 uml_operation_copy(UMLOperation
*op
)
201 newop
= g_new0(UMLOperation
, 1);
203 uml_operation_copy_into(op
, newop
);
204 #if 0 /* setup elsewhere */
205 newop
->left_connection
= g_new0(ConnectionPoint
,1);
206 *newop
->left_connection
= *op
->left_connection
;
207 newop
->left_connection
->object
= NULL
; /* must be setup later */
209 newop
->right_connection
= g_new0(ConnectionPoint
,1);
210 *newop
->right_connection
= *op
->right_connection
;
211 newop
->right_connection
->object
= NULL
; /* must be setup later */
217 uml_operation_destroy(UMLOperation
*op
)
223 if (op
->type
!= NULL
)
225 if (op
->stereotype
!= NULL
)
226 g_free(op
->stereotype
);
230 list
= op
->parameters
;
231 while (list
!= NULL
) {
232 param
= (UMLParameter
*)list
->data
;
233 uml_parameter_destroy(param
);
234 list
= g_list_next(list
);
237 g_list_free(op
->wrappos
);
240 #if 0 /* freed elsewhere */
241 /* These are merely temporary reminders, don't need to unconnect */
242 g_free(op
->left_connection
);
243 g_free(op
->right_connection
);
249 uml_operation_write(AttributeNode attr_node
, UMLOperation
*op
)
255 AttributeNode attr_node2
;
257 composite
= data_add_composite(attr_node
, "umloperation");
259 data_add_string(composite_add_attribute(composite
, "name"),
261 data_add_string(composite_add_attribute(composite
, "stereotype"),
263 data_add_string(composite_add_attribute(composite
, "type"),
265 data_add_enum(composite_add_attribute(composite
, "visibility"),
267 data_add_string(composite_add_attribute(composite
, "comment"),
269 /* Backward compatibility */
270 data_add_boolean(composite_add_attribute(composite
, "abstract"),
271 op
->inheritance_type
== UML_ABSTRACT
);
272 data_add_enum(composite_add_attribute(composite
, "inheritance_type"),
273 op
->inheritance_type
);
274 data_add_boolean(composite_add_attribute(composite
, "query"),
276 data_add_boolean(composite_add_attribute(composite
, "class_scope"),
279 attr_node2
= composite_add_attribute(composite
, "parameters");
281 list
= op
->parameters
;
282 while (list
!= NULL
) {
283 param
= (UMLParameter
*) list
->data
;
285 composite2
= data_add_composite(attr_node2
, "umlparameter");
287 data_add_string(composite_add_attribute(composite2
, "name"),
289 data_add_string(composite_add_attribute(composite2
, "type"),
291 data_add_string(composite_add_attribute(composite2
, "value"),
293 data_add_string(composite_add_attribute(composite2
, "comment"),
295 data_add_enum(composite_add_attribute(composite2
, "kind"),
297 list
= g_list_next(list
);
301 extern char visible_char
[];
304 uml_get_operation_string (UMLOperation
*operation
)
311 /* Calculate length: */
312 len
= 1 + strlen (operation
->name
) + 1;
313 if(operation
->stereotype
!= NULL
&& operation
->stereotype
[0] != '\0') {
314 len
+= 5 + strlen (operation
->stereotype
);
317 list
= operation
->parameters
;
318 while (list
!= NULL
) {
319 param
= (UMLParameter
*) list
->data
;
320 list
= g_list_next (list
);
336 len
+= strlen (param
->name
);
337 if (param
->type
!= NULL
) {
338 len
+= strlen (param
->type
);
339 if (param
->type
[0] && param
->name
[0]) {
343 if (param
->value
!= NULL
&& param
->value
[0] != '\0') {
344 len
+= 1 + strlen (param
->value
);
353 if (operation
->type
!= NULL
&& operation
->type
[0]) {
354 len
+= 2 + strlen (operation
->type
);
356 if(operation
->query
!= 0) {
360 /* generate string: */
361 str
= g_malloc (sizeof (char) * (len
+ 1));
363 str
[0] = visible_char
[(int) operation
->visibility
];
366 if(operation
->stereotype
!= NULL
&& operation
->stereotype
[0] != '\0') {
367 strcat(str
, UML_STEREOTYPE_START
);
368 strcat(str
, operation
->stereotype
);
369 strcat(str
, UML_STEREOTYPE_END
);
373 strcat (str
, operation
->name
);
376 list
= operation
->parameters
;
377 while (list
!= NULL
) {
378 param
= (UMLParameter
*) list
->data
;
379 list
= g_list_next (list
);
389 strcat (str
, "out ");
392 strcat (str
, "inout ");
395 strcat (str
, param
->name
);
397 if (param
->type
!= NULL
) {
398 if (param
->type
[0] && param
->name
[0]) {
401 strcat (str
, param
->type
);
404 if (param
->value
!= NULL
&& param
->value
[0] != '\0') {
406 strcat (str
, param
->value
);
415 if (operation
->type
!= NULL
&&
416 operation
->type
[0]) {
418 strcat (str
, operation
->type
);
421 if (operation
->query
!= 0) {
422 strcat(str
, " const");
425 g_assert (strlen (str
) == len
);
431 * The ownership of these connection points is quite complicated. Instead of being part of the UMLOperation as one may expect
432 * at first, they are somewhat in between the DiaObject (see: DiaObject::connections and the concrete user, here UMLClass)
433 * and the UMLOperation.
434 * But with taking undo state mangement into account it gets even worse. Deleted (to be restored connection points) live inside
435 * the UMLClassChange until they get reverted back to the object *or* get free'd by umlclass_change_free()
436 * Since the implementation of attributes/operations being settable via StdProps there are more places to keep this stuff
437 * consitent. So here comes a tolerant helper.
439 * NOTE: Same function as uml_attribute_ensure_connection_points(), with C++ it would be a template function ;)
442 uml_operation_ensure_connection_points (UMLOperation
* op
, DiaObject
* obj
)
444 if (!op
->left_connection
)
445 op
->left_connection
= g_new0(ConnectionPoint
,1);
446 op
->left_connection
->object
= obj
;
447 if (!op
->right_connection
)
448 op
->right_connection
= g_new0(ConnectionPoint
,1);
449 op
->right_connection
->object
= obj
;