From: Andrea Zagli <azagli@libero.it> Date: Wed, 16 Mar 2016 20:35:58 +0000 (+0100) Subject: Added function ZakGFlowInstance::exclusive_gateway_set_route. X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=d41d547435565f6f872626526ef26ee5c0260807;p=libzakgflow Added function ZakGFlowInstance::exclusive_gateway_set_route. --- diff --git a/.gitignore b/.gitignore index 18e7fe8..719ba45 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,5 @@ Rules-quot *.bpmn !tests/*.bpmn tests/model -tests/instance \ No newline at end of file +tests/instance +tests/exclusive_gateway \ No newline at end of file diff --git a/src/instance.c b/src/instance.c index f76cd56..f95e920 100644 --- a/src/instance.c +++ b/src/instance.c @@ -35,7 +35,7 @@ static void zak_gflow_instance_class_init (ZakGFlowInstanceClass *class); static void zak_gflow_instance_init (ZakGFlowInstance *zak_gflow_instance); -static gchar *zak_gflow_instance_next (ZakGFlowInstance *instance, const gchar *node_id, GNode *cur_node); +static GPtrArray *zak_gflow_instance_next (ZakGFlowInstance *instance, const gchar *node_id, GNode *cur_node); static void zak_gflow_instance_set_property (GObject *object, guint property_id, @@ -77,10 +77,10 @@ zak_gflow_instance_init (ZakGFlowInstance *zak_gflow_instance) priv->nodes_history = g_node_new (NULL); } -static gchar +static GPtrArray *zak_gflow_instance_next (ZakGFlowInstance *instance, const gchar *node_id, GNode *cur_node) { - gchar *ret; + GPtrArray *ret; xmlNode *cur; @@ -90,7 +90,9 @@ static gchar ZakGFlowInstancePrivate *priv; - ret = NULL; + gint i; + + ret = g_ptr_array_new (); priv = zak_gflow_instance_get_instance_private (instance); @@ -106,7 +108,7 @@ static gchar if (xnodeset != NULL && xnodeset->nodeNr > 0) { - ret = g_strdup ((const gchar *)xmlNodeGetContent (xnodeset->nodeTab[0])); + g_ptr_array_add (ret, g_strdup ((const gchar *)xmlNodeGetContent (xnodeset->nodeTab[0]))); zak_gflow_instance_next (instance, (const gchar *)xmlNodeGetContent (xnodeset->nodeTab[0]), _cur_node); } } @@ -114,7 +116,7 @@ static gchar { g_message ("%s: %s (targetRef %s)", cur->name, (gchar *)xmlGetProp (cur, (const xmlChar *)"name"), (gchar *)xmlGetProp (cur, (const xmlChar *)"targetRef")); - ret = g_strdup ((const gchar *)xmlGetProp (cur, (const xmlChar *)"targetRef")); + g_ptr_array_add (ret, g_strdup ((const gchar *)xmlGetProp (cur, (const xmlChar *)"targetRef"))); zak_gflow_instance_next (instance, (const gchar *)xmlGetProp (cur, (const xmlChar *)"targetRef"), _cur_node); } else if (xmlStrcmp (cur->name, (const xmlChar *)"task") == 0 @@ -122,13 +124,20 @@ static gchar { g_message ("%s: %s", cur->name, (gchar *)xmlGetProp (cur, (const xmlChar *)"name")); - ret = g_strdup ((gchar *)xmlGetProp (cur, (const xmlChar *)"id")); + g_ptr_array_add (ret, g_strdup ((gchar *)xmlGetProp (cur, (const xmlChar *)"id"))); } else if (xmlStrcmp (cur->name, (const xmlChar *)"exclusiveGateway") == 0) { g_message ("%s: %s", cur->name, (gchar *)xmlGetProp (cur, (const xmlChar *)"name")); - ret = g_strdup ((gchar *)xmlGetProp (cur, (const xmlChar *)"id")); + xnodeset = zak_gflow_commons_xml_search (priv->xpcontext, cur, (const xmlChar *)"child::bpmn:outgoing"); + if (xnodeset != NULL) + { + for (i = 0; i < xnodeset->nodeNr; i++) + { + g_ptr_array_add (ret, g_strdup ((const gchar *)xmlNodeGetContent (xnodeset->nodeTab[i]))); + } + } } else { @@ -223,8 +232,9 @@ GPtrArray xmlNodeSet *xnodeset; gint i; + guint j; - gchar *cur_node_id; + GPtrArray *cur_nodes_id; ZakGFlowInstancePrivate *priv = zak_gflow_instance_get_instance_private (instance); @@ -237,24 +247,30 @@ GPtrArray G_POST_ORDER, G_TRAVERSE_LEAVES, xnode); - if (node != NULL) + if (xmlStrcmp (xnode->name, (const xmlChar *)"task") != 0 + && xmlStrcmp (xnode->name, (const xmlChar *)"userTask") != 0) + { + g_warning ("The node <%s> isn't a task: it cannot be completed.", node_id); + } + else if (node != NULL) { /* move to next */ xnodeset = zak_gflow_commons_xml_search (priv->xpcontext, xnode, (const xmlChar *)"child::bpmn:outgoing"); - if (xnodeset != NULL - && xnodeset->nodeNr > 0) + if (xnodeset != NULL) { for (i = 0; i < xnodeset->nodeNr; i++) { - cur_node_id = zak_gflow_instance_next (instance, (const gchar *)xmlNodeGetContent (xnodeset->nodeTab[i]), node); - g_ptr_array_add (ret, g_strdup (cur_node_id)); - g_free (cur_node_id); + cur_nodes_id = zak_gflow_instance_next (instance, (const gchar *)xmlNodeGetContent (xnodeset->nodeTab[i]), node); + for (j = 0; j < cur_nodes_id->len; j++) + { + g_ptr_array_add (ret, g_strdup (g_ptr_array_index (cur_nodes_id, j))); + } } } } else { - g_warning ("The node <%s> isn't a waiting node", node_id); + g_warning ("The node <%s> isn't a waiting node.", node_id); } } else @@ -265,6 +281,60 @@ GPtrArray return ret; } +/** + * zak_gflow_instance_exclusive_gateway_set_route: + * @instance: + * @node_id: + * @route_id: + * + */ +GPtrArray +*zak_gflow_instance_exclusive_gateway_set_route (ZakGFlowInstance *instance, const gchar *node_id, const gchar *route_id) +{ + GPtrArray *ret; + + xmlNode *xnode; + + GNode *node; + + xmlNodeSet *xnodeset; + + guint i; + + GPtrArray *cur_nodes_id; + + ZakGFlowInstancePrivate *priv = zak_gflow_instance_get_instance_private (instance); + + ret = g_ptr_array_new (); + + xnode = (xmlNode *)g_hash_table_lookup (priv->ht_nodes, node_id); + if (xnode != NULL) + { + node = g_node_find (priv->nodes_history, + G_POST_ORDER, + G_TRAVERSE_LEAVES, + xnode); + if (xmlStrcmp (xnode->name, (const xmlChar *)"exclusiveGateway") != 0) + { + g_warning ("The node <%s> isn't an exclusive gateway.", node_id); + } + else if (node != NULL) + { + cur_nodes_id = zak_gflow_instance_next (instance, route_id, node); + for (i = 0; i < cur_nodes_id->len; i++) + { + g_ptr_array_add (ret, g_strdup (g_ptr_array_index (cur_nodes_id, i))); + } + } + else + { + g_warning ("The node <%s> isn't a waiting node.", node_id); + } + } + + return ret; +} + /* PRIVATE */ static void zak_gflow_instance_set_property (GObject *object, diff --git a/src/instance.h b/src/instance.h index 883f497..796c60f 100644 --- a/src/instance.h +++ b/src/instance.h @@ -44,6 +44,8 @@ GPtrArray *zak_gflow_instance_get_current_nodes (ZakGFlowInstance *instance); GPtrArray *zak_gflow_instance_task_complete (ZakGFlowInstance *instance, const gchar *node_id); +GPtrArray *zak_gflow_instance_exclusive_gateway_set_route (ZakGFlowInstance *instance, const gchar *node_id, const gchar *route_id); + G_END_DECLS diff --git a/tests/Makefile.am b/tests/Makefile.am index 0e510da..0b5653a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,7 +10,8 @@ LDADD = $(top_builddir)/src/libzakgflow.la noinst_PROGRAMS = \ model \ - instance + instance \ + exclusive_gateway EXTRADIST = \ diagram.bpmn diff --git a/tests/exclusive_gateway.bpmn b/tests/exclusive_gateway.bpmn new file mode 100644 index 0000000..3219737 --- /dev/null +++ b/tests/exclusive_gateway.bpmn @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"> + <bpmn:process id="Process_1" isExecutable="false"> + <bpmn:startEvent id="StartEvent_1"> + <bpmn:outgoing>SequenceFlow_0ltcl3v</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:exclusiveGateway id="ExclusiveGateway_0931occ"> + <bpmn:incoming>SequenceFlow_0ltcl3v</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_1uv2bmp</bpmn:outgoing> + <bpmn:outgoing>SequenceFlow_05cclyv</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="SequenceFlow_0ltcl3v" sourceRef="StartEvent_1" targetRef="ExclusiveGateway_0931occ" /> + <bpmn:task id="Task_01ub4ta" name="approved"> + <bpmn:incoming>SequenceFlow_1uv2bmp</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_005y1vw</bpmn:outgoing> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_1uv2bmp" sourceRef="ExclusiveGateway_0931occ" targetRef="Task_01ub4ta" /> + <bpmn:task id="Task_0ceadr7" name="rejected"> + <bpmn:incoming>SequenceFlow_05cclyv</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0gxnj5p</bpmn:outgoing> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_05cclyv" sourceRef="ExclusiveGateway_0931occ" targetRef="Task_0ceadr7" /> + <bpmn:endEvent id="EndEvent_0uyi6wa"> + <bpmn:incoming>SequenceFlow_0gxnj5p</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="SequenceFlow_0gxnj5p" sourceRef="Task_0ceadr7" targetRef="EndEvent_0uyi6wa" /> + <bpmn:endEvent id="EndEvent_1ci8lj8"> + <bpmn:incoming>SequenceFlow_005y1vw</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="SequenceFlow_005y1vw" sourceRef="Task_01ub4ta" targetRef="EndEvent_1ci8lj8" /> + </bpmn:process> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"> + <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> + <dc:Bounds x="173" y="102" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ExclusiveGateway_0931occ_di" bpmnElement="ExclusiveGateway_0931occ" isMarkerVisible="true"> + <dc:Bounds x="293" y="95" width="50" height="50" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="273" y="145" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_0ltcl3v_di" bpmnElement="SequenceFlow_0ltcl3v"> + <di:waypoint xsi:type="dc:Point" x="209" y="120" /> + <di:waypoint xsi:type="dc:Point" x="293" y="120" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="225.5" y="110" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Task_01ub4ta_di" bpmnElement="Task_01ub4ta"> + <dc:Bounds x="471" y="80" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_1uv2bmp_di" bpmnElement="SequenceFlow_1uv2bmp"> + <di:waypoint xsi:type="dc:Point" x="343" y="120" /> + <di:waypoint xsi:type="dc:Point" x="471" y="120" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="362" y="110" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Task_0ceadr7_di" bpmnElement="Task_0ceadr7"> + <dc:Bounds x="268" y="231" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_05cclyv_di" bpmnElement="SequenceFlow_05cclyv"> + <di:waypoint xsi:type="dc:Point" x="318" y="145" /> + <di:waypoint xsi:type="dc:Point" x="318" y="231" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="273" y="178" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="EndEvent_0uyi6wa_di" bpmnElement="EndEvent_0uyi6wa"> + <dc:Bounds x="300" y="368" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="273" y="404" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_0gxnj5p_di" bpmnElement="SequenceFlow_0gxnj5p"> + <di:waypoint xsi:type="dc:Point" x="318" y="311" /> + <di:waypoint xsi:type="dc:Point" x="318" y="368" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="273" y="329.5" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="EndEvent_1ci8lj8_di" bpmnElement="EndEvent_1ci8lj8"> + <dc:Bounds x="651" y="102" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="624" y="138" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_005y1vw_di" bpmnElement="SequenceFlow_005y1vw"> + <di:waypoint xsi:type="dc:Point" x="571" y="120" /> + <di:waypoint xsi:type="dc:Point" x="607" y="120" /> + <di:waypoint xsi:type="dc:Point" x="607" y="120" /> + <di:waypoint xsi:type="dc:Point" x="651" y="120" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="562" y="114.5" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/tests/exclusive_gateway.c b/tests/exclusive_gateway.c new file mode 100644 index 0000000..455d02e --- /dev/null +++ b/tests/exclusive_gateway.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Andrea Zagli <azagli@libero.it> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <glib/gstdio.h> + +#include "model.h" +#include "instance.h" + +int +main (int argc, char *argv[]) +{ + ZakGFlowModel *model; + ZakGFlowInstance *instance; + GPtrArray *ar; + + guint i; + + model = zak_gflow_model_new_from_file (argv[1]); + if (model == NULL) + { + g_warning ("No model loaded from xml file <%s>.", argv[1]); + } + else + { + instance = zak_gflow_model_start (model, argv[2]); + + /* wrong node_id */ + zak_gflow_instance_exclusive_gateway_set_route (instance, "jon_doe", "new_route"); + + /* right node_id */ + ar = zak_gflow_instance_exclusive_gateway_set_route (instance, "ExclusiveGateway_0931occ", "SequenceFlow_1uv2bmp");//05cclyv"); + for (i = 0; i < ar->len; i++) + { + g_printf ("Currente node after exclusive_gateway_set_route: %s\n", (gchar *)g_ptr_array_index (ar, i)); + } + + /* general current nodes */ + ar = zak_gflow_instance_get_current_nodes (instance); + for (i = 0; i < ar->len; i++) + { + g_printf ("Currente node: %s\n", (gchar *)g_ptr_array_index (ar, i)); + } + } + + return 0; +} diff --git a/tests/multiple_task_outgoing.bpmn b/tests/multiple_task_outgoing.bpmn new file mode 100644 index 0000000..338366c --- /dev/null +++ b/tests/multiple_task_outgoing.bpmn @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"> + <bpmn:process id="Process_1" isExecutable="false"> + <bpmn:startEvent id="StartEvent_1"> + <bpmn:outgoing>SequenceFlow_1okaoto</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:task id="Task_1mry6ve"> + <bpmn:incoming>SequenceFlow_1okaoto</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0cd9wu5</bpmn:outgoing> + <bpmn:outgoing>SequenceFlow_16m0ajv</bpmn:outgoing> + <bpmn:outgoing>SequenceFlow_0vq4xcx</bpmn:outgoing> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_1okaoto" sourceRef="StartEvent_1" targetRef="Task_1mry6ve" /> + <bpmn:task id="Task_1uh9c57"> + <bpmn:incoming>SequenceFlow_0cd9wu5</bpmn:incoming> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_0cd9wu5" sourceRef="Task_1mry6ve" targetRef="Task_1uh9c57" /> + <bpmn:task id="Task_06lxgav"> + <bpmn:incoming>SequenceFlow_16m0ajv</bpmn:incoming> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_16m0ajv" sourceRef="Task_1mry6ve" targetRef="Task_06lxgav" /> + <bpmn:task id="Task_05zs44q"> + <bpmn:incoming>SequenceFlow_0vq4xcx</bpmn:incoming> + </bpmn:task> + <bpmn:sequenceFlow id="SequenceFlow_0vq4xcx" sourceRef="Task_1mry6ve" targetRef="Task_05zs44q" /> + </bpmn:process> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"> + <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> + <dc:Bounds x="173" y="102" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Task_1mry6ve_di" bpmnElement="Task_1mry6ve"> + <dc:Bounds x="282" y="153" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_1okaoto_di" bpmnElement="SequenceFlow_1okaoto"> + <di:waypoint xsi:type="dc:Point" x="209" y="120" /> + <di:waypoint xsi:type="dc:Point" x="246" y="120" /> + <di:waypoint xsi:type="dc:Point" x="246" y="193" /> + <di:waypoint xsi:type="dc:Point" x="282" y="193" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="198" y="110" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Task_1uh9c57_di" bpmnElement="Task_1uh9c57"> + <dc:Bounds x="496" y="48" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_0cd9wu5_di" bpmnElement="SequenceFlow_0cd9wu5"> + <di:waypoint xsi:type="dc:Point" x="382" y="193" /> + <di:waypoint xsi:type="dc:Point" x="439" y="193" /> + <di:waypoint xsi:type="dc:Point" x="439" y="88" /> + <di:waypoint xsi:type="dc:Point" x="496" y="88" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="394" y="130.5" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Task_06lxgav_di" bpmnElement="Task_06lxgav"> + <dc:Bounds x="509" y="203" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_16m0ajv_di" bpmnElement="SequenceFlow_16m0ajv"> + <di:waypoint xsi:type="dc:Point" x="382" y="193" /> + <di:waypoint xsi:type="dc:Point" x="446" y="193" /> + <di:waypoint xsi:type="dc:Point" x="446" y="243" /> + <di:waypoint xsi:type="dc:Point" x="509" y="243" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="401" y="208" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Task_05zs44q_di" bpmnElement="Task_05zs44q"> + <dc:Bounds x="509" y="345" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="SequenceFlow_0vq4xcx_di" bpmnElement="SequenceFlow_0vq4xcx"> + <di:waypoint xsi:type="dc:Point" x="382" y="193" /> + <di:waypoint xsi:type="dc:Point" x="446" y="193" /> + <di:waypoint xsi:type="dc:Point" x="446" y="385" /> + <di:waypoint xsi:type="dc:Point" x="509" y="385" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="401" y="279" width="90" height="20" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions>