349 lines
18 KiB
Diff
349 lines
18 KiB
Diff
diff --git a/SpiffWorkflow/spiff/parser/process.py b/SpiffWorkflow/spiff/parser/process.py
|
|
index 4abdb96..2ec536f 100644
|
|
--- a/SpiffWorkflow/spiff/parser/process.py
|
|
+++ b/SpiffWorkflow/spiff/parser/process.py
|
|
@@ -2,9 +2,9 @@ from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser
|
|
from SpiffWorkflow.bpmn.parser.BpmnParser import full_tag
|
|
|
|
from SpiffWorkflow.bpmn.specs.events import StartEvent, EndEvent, IntermediateThrowEvent, BoundaryEvent, IntermediateCatchEvent
|
|
-from SpiffWorkflow.spiff.specs import NoneTask, ManualTask, UserTask, SubWorkflowTask, TransactionSubprocess, CallActivity, ServiceTask
|
|
+from SpiffWorkflow.spiff.specs import NoneTask, ManualTask, UserTask, ScriptTask, SubWorkflowTask, TransactionSubprocess, CallActivity, ServiceTask
|
|
from SpiffWorkflow.spiff.specs.events.event_types import SendTask, ReceiveTask
|
|
-from SpiffWorkflow.spiff.parser.task_spec import SpiffTaskParser, SubWorkflowParser, CallActivityParser, ServiceTaskParser
|
|
+from SpiffWorkflow.spiff.parser.task_spec import SpiffTaskParser, SubWorkflowParser, CallActivityParser, ServiceTaskParser, ScriptTaskParser
|
|
from SpiffWorkflow.spiff.parser.event_parsers import (SpiffStartEventParser, SpiffEndEventParser, SpiffBoundaryEventParser,
|
|
SpiffIntermediateCatchEventParser, SpiffIntermediateThrowEventParser, SpiffSendTaskParser, SpiffReceiveTaskParser)
|
|
from SpiffWorkflow.dmn.specs import BusinessRuleTask
|
|
@@ -17,6 +17,7 @@ class SpiffBpmnParser(BpmnDmnParser):
|
|
full_tag('task'): (SpiffTaskParser, NoneTask),
|
|
full_tag('userTask'): (SpiffTaskParser, UserTask),
|
|
full_tag('manualTask'): (SpiffTaskParser, ManualTask),
|
|
+ full_tag('scriptTask'): (ScriptTaskParser, ScriptTask),
|
|
full_tag('subProcess'): (SubWorkflowParser, SubWorkflowTask),
|
|
full_tag('transaction'): (SubWorkflowParser, TransactionSubprocess),
|
|
full_tag('callActivity'): (CallActivityParser, CallActivity),
|
|
diff --git a/SpiffWorkflow/spiff/parser/task_spec.py b/SpiffWorkflow/spiff/parser/task_spec.py
|
|
index 32e8ecf..da3961d 100644
|
|
--- a/SpiffWorkflow/spiff/parser/task_spec.py
|
|
+++ b/SpiffWorkflow/spiff/parser/task_spec.py
|
|
@@ -6,6 +6,7 @@ from SpiffWorkflow.bpmn.parser.task_parsers import SubprocessParser
|
|
from SpiffWorkflow.bpmn.parser.util import xpath_eval
|
|
|
|
SPIFFWORKFLOW_MODEL_NS = 'http://spiffworkflow.org/bpmn/schema/1.0/core'
|
|
+SPIFFWORKFLOW_MODEL_PREFIX = 'spiffworkflow'
|
|
|
|
|
|
class SpiffTaskParser(TaskParser):
|
|
@@ -20,36 +21,55 @@ class SpiffTaskParser(TaskParser):
|
|
# Too bad doing this works in such a stupid way.
|
|
# We should set a namespace and automatically do this.
|
|
extensions = {}
|
|
- extra_ns = {'spiffworkflow': SPIFFWORKFLOW_MODEL_NS}
|
|
+ extra_ns = {SPIFFWORKFLOW_MODEL_PREFIX: SPIFFWORKFLOW_MODEL_NS}
|
|
xpath = xpath_eval(node, extra_ns)
|
|
- extension_nodes = xpath('.//bpmn:extensionElements/spiffworkflow:*')
|
|
+ extension_nodes = xpath(f'.//bpmn:extensionElements/{SPIFFWORKFLOW_MODEL_PREFIX}:*')
|
|
for node in extension_nodes:
|
|
name = etree.QName(node).localname
|
|
if name == 'properties':
|
|
extensions['properties'] = SpiffTaskParser._parse_properties(node)
|
|
+ elif name == 'unitTests':
|
|
+ extensions['unitTests'] = SpiffTaskParser._parse_script_unit_tests(node)
|
|
elif name == 'serviceTaskOperator':
|
|
extensions['serviceTaskOperator'] = SpiffTaskParser._parse_servicetask_operator(node)
|
|
else:
|
|
extensions[name] = node.text
|
|
return extensions
|
|
|
|
- @staticmethod
|
|
- def _parse_properties(node):
|
|
- extra_ns = {'spiffworkflow': SPIFFWORKFLOW_MODEL_NS}
|
|
- xpath = xpath_eval(node, extra_ns)
|
|
- property_nodes = xpath('.//spiffworkflow:property')
|
|
+ @classmethod
|
|
+ def _node_children_by_tag_name(cls, node, tag_name):
|
|
+ xpath = cls._spiffworkflow_ready_xpath_for_node(node)
|
|
+ return xpath(f'.//{SPIFFWORKFLOW_MODEL_PREFIX}:{tag_name}')
|
|
+
|
|
+ @classmethod
|
|
+ def _parse_properties(cls, node):
|
|
+ property_nodes = cls._node_children_by_tag_name(node, 'property')
|
|
properties = {}
|
|
for prop_node in property_nodes:
|
|
properties[prop_node.attrib['name']] = prop_node.attrib['value']
|
|
return properties
|
|
|
|
@staticmethod
|
|
- def _parse_servicetask_operator(node):
|
|
+ def _spiffworkflow_ready_xpath_for_node(node):
|
|
+ extra_ns = {SPIFFWORKFLOW_MODEL_PREFIX: SPIFFWORKFLOW_MODEL_NS}
|
|
+ return xpath_eval(node, extra_ns)
|
|
+
|
|
+ @classmethod
|
|
+ def _parse_script_unit_tests(cls, node):
|
|
+ unit_test_nodes = cls._node_children_by_tag_name(node, 'unitTest')
|
|
+ unit_tests = []
|
|
+ for unit_test_node in unit_test_nodes:
|
|
+ unit_test_dict = {"id": unit_test_node.attrib['id']}
|
|
+ unit_test_dict['inputJson'] = cls._node_children_by_tag_name(unit_test_node, 'inputJson')[0].text
|
|
+ unit_test_dict['expectedOutputJson'] = cls._node_children_by_tag_name(unit_test_node, 'expectedOutputJson')[0].text
|
|
+ unit_tests.append(unit_test_dict)
|
|
+ return unit_tests
|
|
+
|
|
+ @classmethod
|
|
+ def _parse_servicetask_operator(cls, node):
|
|
name = node.attrib['id']
|
|
result_variable = node.get('resultVariable', None)
|
|
- extra_ns = {'spiffworkflow': SPIFFWORKFLOW_MODEL_NS}
|
|
- xpath = xpath_eval(node, extra_ns)
|
|
- parameter_nodes = xpath('.//spiffworkflow:parameter')
|
|
+ parameter_nodes = cls._node_children_by_tag_name(node, 'parameter')
|
|
operator = {'name': name, 'resultVariable': result_variable}
|
|
parameters = {}
|
|
for param_node in parameter_nodes:
|
|
@@ -92,6 +112,20 @@ class SubWorkflowParser(SpiffTaskParser):
|
|
postscript=postscript)
|
|
|
|
|
|
+class ScriptTaskParser(SpiffTaskParser):
|
|
+ def create_task(self):
|
|
+ extensions = self.parse_extensions()
|
|
+ script = None
|
|
+ for child_node in self.node:
|
|
+ if child_node.tag.endswith('script'):
|
|
+ script = child_node.text
|
|
+ # import pdb; pdb.set_trace()
|
|
+ return self.spec_class(
|
|
+ self.spec, self.get_task_spec_name(), script,
|
|
+ lane=self.lane, position=self.position,
|
|
+ description=self.node.get('name', None))
|
|
+
|
|
+
|
|
class CallActivityParser(SpiffTaskParser):
|
|
|
|
def create_task(self):
|
|
diff --git a/SpiffWorkflow/spiff/serializer/__init__.py b/SpiffWorkflow/spiff/serializer/__init__.py
|
|
index 4ba82d6..364c3eb 100644
|
|
--- a/SpiffWorkflow/spiff/serializer/__init__.py
|
|
+++ b/SpiffWorkflow/spiff/serializer/__init__.py
|
|
@@ -1,4 +1,4 @@
|
|
-from .task_spec_converters import NoneTaskConverter, ManualTaskConverter, UserTaskConverter
|
|
+from .task_spec_converters import NoneTaskConverter, ManualTaskConverter, UserTaskConverter, ScriptTaskConverter
|
|
from .task_spec_converters import TransactionSubprocessConverter, CallActivityTaskConverter, SubWorkflowTaskConverter
|
|
from .task_spec_converters import StartEventConverter, EndEventConverter, IntermediateCatchEventConverter, IntermediateThrowEventConverter, \
|
|
BoundaryEventConverter, SendTaskConverter, ReceiveTaskConverter, ServiceTaskConverter
|
|
diff --git a/SpiffWorkflow/spiff/serializer/task_spec_converters.py b/SpiffWorkflow/spiff/serializer/task_spec_converters.py
|
|
index 8c25970..5b24278 100644
|
|
--- a/SpiffWorkflow/spiff/serializer/task_spec_converters.py
|
|
+++ b/SpiffWorkflow/spiff/serializer/task_spec_converters.py
|
|
@@ -2,7 +2,7 @@ from functools import partial
|
|
|
|
from SpiffWorkflow.bpmn.serializer.bpmn_converters import BpmnTaskSpecConverter
|
|
from SpiffWorkflow.bpmn.specs.events import EndEvent, StartEvent, IntermediateThrowEvent, IntermediateCatchEvent, BoundaryEvent
|
|
-from SpiffWorkflow.spiff.specs import NoneTask, ManualTask, UserTask, ServiceTask, SubWorkflowTask, TransactionSubprocess, CallActivity
|
|
+from SpiffWorkflow.spiff.specs import NoneTask, ManualTask, UserTask, ScriptTask, ServiceTask, SubWorkflowTask, TransactionSubprocess, CallActivity
|
|
from SpiffWorkflow.spiff.specs.events import SendTask, ReceiveTask
|
|
from SpiffWorkflow.spiff.specs.events.event_definitions import MessageEventDefinition
|
|
|
|
@@ -35,6 +35,16 @@ class UserTaskConverter(SpiffBpmnTaskConverter):
|
|
super().__init__(UserTask, data_converter)
|
|
|
|
|
|
+class ScriptTaskConverter(SpiffBpmnTaskConverter):
|
|
+ def __init__(self, data_converter=None):
|
|
+ super().__init__(ScriptTask, data_converter)
|
|
+
|
|
+ def to_dict(self, spec):
|
|
+ dct = super().to_dict(spec)
|
|
+ dct['script'] = spec.script
|
|
+ return dct
|
|
+
|
|
+
|
|
class ServiceTaskConverter(SpiffBpmnTaskConverter):
|
|
def __init__(self, data_converter=None):
|
|
super().__init__(ServiceTask, data_converter)
|
|
diff --git a/SpiffWorkflow/spiff/specs/__init__.py b/SpiffWorkflow/spiff/specs/__init__.py
|
|
index 5378a5b..1e18b63 100644
|
|
--- a/SpiffWorkflow/spiff/specs/__init__.py
|
|
+++ b/SpiffWorkflow/spiff/specs/__init__.py
|
|
@@ -2,4 +2,5 @@ from .manual_task import ManualTask
|
|
from .none_task import NoneTask
|
|
from .subworkflow_task import SubWorkflowTask, TransactionSubprocess, CallActivity
|
|
from .user_task import UserTask
|
|
+from .script_task import ScriptTask
|
|
from .service_task import ServiceTask
|
|
diff --git a/SpiffWorkflow/spiff/specs/script_task.py b/SpiffWorkflow/spiff/specs/script_task.py
|
|
new file mode 100644
|
|
index 0000000..c56e7e8
|
|
--- /dev/null
|
|
+++ b/SpiffWorkflow/spiff/specs/script_task.py
|
|
@@ -0,0 +1,6 @@
|
|
+from SpiffWorkflow.spiff.specs.spiff_task import SpiffBpmnTask
|
|
+from SpiffWorkflow.bpmn.specs.ScriptTask import ScriptTask as BpmnScriptTask
|
|
+
|
|
+
|
|
+class ScriptTask(BpmnScriptTask, SpiffBpmnTask):
|
|
+ pass
|
|
diff --git a/tests/SpiffWorkflow/spiff/BaseTestCase.py b/tests/SpiffWorkflow/spiff/BaseTestCase.py
|
|
index 92c23eb..248f84a 100644
|
|
--- a/tests/SpiffWorkflow/spiff/BaseTestCase.py
|
|
+++ b/tests/SpiffWorkflow/spiff/BaseTestCase.py
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
|
from SpiffWorkflow.spiff.parser import SpiffBpmnParser
|
|
from SpiffWorkflow.spiff.serializer import NoneTaskConverter, \
|
|
- ManualTaskConverter, UserTaskConverter, \
|
|
+ ManualTaskConverter, UserTaskConverter, ScriptTaskConverter, \
|
|
SubWorkflowTaskConverter, TransactionSubprocessConverter, \
|
|
CallActivityTaskConverter, \
|
|
StartEventConverter, EndEventConverter, BoundaryEventConverter, \
|
|
@@ -16,7 +16,7 @@ from SpiffWorkflow.bpmn.serializer import BpmnWorkflowSerializer
|
|
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
|
|
|
|
wf_spec_converter = BpmnWorkflowSerializer.configure_workflow_spec_converter([
|
|
- NoneTaskConverter, ManualTaskConverter, UserTaskConverter,
|
|
+ NoneTaskConverter, ManualTaskConverter, UserTaskConverter, ScriptTaskConverter,
|
|
SubWorkflowTaskConverter, TransactionSubprocessConverter, CallActivityTaskConverter,
|
|
StartEventConverter, EndEventConverter, BoundaryEventConverter, SendTaskConverter, ReceiveTaskConverter,
|
|
IntermediateCatchEventConverter, IntermediateThrowEventConverter, BusinessRuleTaskConverter,
|
|
diff --git a/tests/SpiffWorkflow/spiff/ScriptUnitTestExtensionsTest.py b/tests/SpiffWorkflow/spiff/ScriptUnitTestExtensionsTest.py
|
|
new file mode 100644
|
|
index 0000000..87c8335
|
|
--- /dev/null
|
|
+++ b/tests/SpiffWorkflow/spiff/ScriptUnitTestExtensionsTest.py
|
|
@@ -0,0 +1,46 @@
|
|
+from SpiffWorkflow.task import TaskState
|
|
+from .BaseTestCase import BaseTestCase
|
|
+from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
|
|
+
|
|
+# Assure we correctly parse and pass on the Spiffworkflow properties in
|
|
+# an extension.
|
|
+class ScriptUnitTestExtensionsTest(BaseTestCase):
|
|
+
|
|
+ def testTask(self):
|
|
+ self.task_test()
|
|
+
|
|
+ def testTaskSaveRestore(self):
|
|
+ self.task_test(True)
|
|
+
|
|
+ def task_test(self, save_restore=False):
|
|
+
|
|
+ spec, subprocesses = self.load_workflow_spec('script_task_with_unit_tests.bpmn', 'Process_ScriptTaskWithUnitTests')
|
|
+ self.workflow = BpmnWorkflow(spec, subprocesses)
|
|
+ self.workflow.do_engine_steps()
|
|
+ if save_restore:
|
|
+ self.save_restore()
|
|
+
|
|
+ # unitTests should be a list of dicts
|
|
+ expected_unit_tests_wrapper_class_name = 'list'
|
|
+ expected_unit_test_class_name = 'dict'
|
|
+
|
|
+ script_with_unit_tests = [t for t in self.workflow.get_tasks() if
|
|
+ t.task_spec.name == 'script_with_unit_test_id'][0]
|
|
+ print(f"script_with_unit_tests.task_spec.extensions: {script_with_unit_tests.task_spec.extensions}")
|
|
+ extensions = script_with_unit_tests.task_spec.extensions
|
|
+ unit_test_extensions = extensions['unitTests']
|
|
+ print(f"unit_test_extensions: {unit_test_extensions}")
|
|
+ print(f"unit_test_extensions.class: {unit_test_extensions.__class__.__name__}")
|
|
+ unit_test_extensions_class_name = unit_test_extensions.__class__.__name__
|
|
+ self.assertEqual(unit_test_extensions_class_name, expected_unit_tests_wrapper_class_name)
|
|
+ self.assertEqual(len(unit_test_extensions), 2)
|
|
+ first_unit_test = unit_test_extensions[0]
|
|
+ self.assertEqual(first_unit_test.__class__.__name__, expected_unit_test_class_name)
|
|
+ expected_first_unit_test = {'id': 'sets_hey_to_true_if_hey_is_false',
|
|
+ 'inputJson': '{"hey": false}', 'expectedOutputJson': '{"hey": true}'}
|
|
+ self.assertDictEqual(first_unit_test, expected_first_unit_test)
|
|
+ # self.assertEqual(len(unit_test_extensions), 2)
|
|
+ # self.assertDictEqual({'formJsonSchemaFilename': 'my_json_jschema.json',
|
|
+ # 'formUiSchemaFilename': 'my_ui_jschema.json'},
|
|
+ # task.task_spec.extensions)
|
|
+
|
|
diff --git a/tests/SpiffWorkflow/spiff/SpiffPropertiesTest.py b/tests/SpiffWorkflow/spiff/SpiffPropertiesTest.py
|
|
index d029f35..9087aae 100644
|
|
--- a/tests/SpiffWorkflow/spiff/SpiffPropertiesTest.py
|
|
+++ b/tests/SpiffWorkflow/spiff/SpiffPropertiesTest.py
|
|
@@ -4,7 +4,7 @@ from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
|
|
|
|
# Assure we correctly parse and pass on the Spiffworkflow properties in
|
|
# an extension.
|
|
-class SpiffWorkflowProperties(BaseTestCase):
|
|
+class SpiffPropertiesTest(BaseTestCase):
|
|
|
|
def testTask(self):
|
|
self.task_test()
|
|
diff --git a/tests/SpiffWorkflow/spiff/data/script_task_with_unit_tests.bpmn b/tests/SpiffWorkflow/spiff/data/script_task_with_unit_tests.bpmn
|
|
new file mode 100644
|
|
index 0000000..d2873b8
|
|
--- /dev/null
|
|
+++ b/tests/SpiffWorkflow/spiff/data/script_task_with_unit_tests.bpmn
|
|
@@ -0,0 +1,69 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<bpmn:definitions 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" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1ny7jp4" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
|
|
+ <bpmn:process id="Process_ScriptTaskWithUnitTests" isExecutable="true">
|
|
+ <bpmn:startEvent id="StartEvent_1">
|
|
+ <bpmn:outgoing>Flow_10jwwqy</bpmn:outgoing>
|
|
+ </bpmn:startEvent>
|
|
+ <bpmn:sequenceFlow id="Flow_10jwwqy" sourceRef="StartEvent_1" targetRef="Activity_03fldr6" />
|
|
+ <bpmn:endEvent id="Event_1qb1u6a">
|
|
+ <bpmn:incoming>Flow_0htxke7</bpmn:incoming>
|
|
+ </bpmn:endEvent>
|
|
+ <bpmn:sequenceFlow id="Flow_0htxke7" sourceRef="script_with_unit_test_id" targetRef="Event_1qb1u6a" />
|
|
+ <bpmn:scriptTask id="script_with_unit_test_id" name="Script with unit test">
|
|
+ <bpmn:extensionElements>
|
|
+ <spiffworkflow:unitTests>
|
|
+ <spiffworkflow:unitTest id="sets_hey_to_true_if_hey_is_false">
|
|
+ <spiffworkflow:inputJson>{"hey": false}</spiffworkflow:inputJson>
|
|
+ <spiffworkflow:expectedOutputJson>{"hey": true}</spiffworkflow:expectedOutputJson>
|
|
+ </spiffworkflow:unitTest>
|
|
+ <spiffworkflow:unitTest id="sets_something_else_if_no_hey">
|
|
+ <spiffworkflow:inputJson>{}</spiffworkflow:inputJson>
|
|
+ <spiffworkflow:expectedOutputJson>{"something_else": true}</spiffworkflow:expectedOutputJson>
|
|
+ </spiffworkflow:unitTest>
|
|
+ </spiffworkflow:unitTests>
|
|
+ </bpmn:extensionElements>
|
|
+ <bpmn:incoming>Flow_0niwe1y</bpmn:incoming>
|
|
+ <bpmn:outgoing>Flow_0htxke7</bpmn:outgoing>
|
|
+ <bpmn:script>if 'hey' in locals():
|
|
+ hey = True
|
|
+else:
|
|
+ something_else = True</bpmn:script>
|
|
+ </bpmn:scriptTask>
|
|
+ <bpmn:sequenceFlow id="Flow_0niwe1y" sourceRef="Activity_03fldr6" targetRef="script_with_unit_test_id" />
|
|
+ <bpmn:scriptTask id="Activity_03fldr6" name="Set var">
|
|
+ <bpmn:incoming>Flow_10jwwqy</bpmn:incoming>
|
|
+ <bpmn:outgoing>Flow_0niwe1y</bpmn:outgoing>
|
|
+ <bpmn:script>hey = False</bpmn:script>
|
|
+ </bpmn:scriptTask>
|
|
+ </bpmn:process>
|
|
+ <bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
|
+ <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="sample">
|
|
+ <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
|
+ <dc:Bounds x="132" y="102" width="36" height="36" />
|
|
+ </bpmndi:BPMNShape>
|
|
+ <bpmndi:BPMNShape id="Event_1qb1u6a_di" bpmnElement="Event_1qb1u6a">
|
|
+ <dc:Bounds x="642" y="102" width="36" height="36" />
|
|
+ </bpmndi:BPMNShape>
|
|
+ <bpmndi:BPMNShape id="Activity_17ohe7r_di" bpmnElement="script_with_unit_test_id">
|
|
+ <dc:Bounds x="440" y="80" width="100" height="80" />
|
|
+ <bpmndi:BPMNLabel />
|
|
+ </bpmndi:BPMNShape>
|
|
+ <bpmndi:BPMNShape id="Activity_1fab1y2_di" bpmnElement="Activity_03fldr6">
|
|
+ <dc:Bounds x="250" y="80" width="100" height="80" />
|
|
+ <bpmndi:BPMNLabel />
|
|
+ </bpmndi:BPMNShape>
|
|
+ <bpmndi:BPMNEdge id="Flow_10jwwqy_di" bpmnElement="Flow_10jwwqy">
|
|
+ <di:waypoint x="168" y="120" />
|
|
+ <di:waypoint x="250" y="120" />
|
|
+ </bpmndi:BPMNEdge>
|
|
+ <bpmndi:BPMNEdge id="Flow_0htxke7_di" bpmnElement="Flow_0htxke7">
|
|
+ <di:waypoint x="540" y="120" />
|
|
+ <di:waypoint x="642" y="120" />
|
|
+ </bpmndi:BPMNEdge>
|
|
+ <bpmndi:BPMNEdge id="Flow_0niwe1y_di" bpmnElement="Flow_0niwe1y">
|
|
+ <di:waypoint x="350" y="120" />
|
|
+ <di:waypoint x="440" y="120" />
|
|
+ </bpmndi:BPMNEdge>
|
|
+ </bpmndi:BPMNPlane>
|
|
+ </bpmndi:BPMNDiagram>
|
|
+</bpmn:definitions>
|