Skip to content

Commit

Permalink
Merge pull request #373 from sartography/feature/data-object-category
Browse files Browse the repository at this point in the history
Feature/data object category
  • Loading branch information
jasquat authored Dec 8, 2023
2 parents 1f8cffb + a62fa97 commit e4ceff4
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 12 deletions.
8 changes: 4 additions & 4 deletions SpiffWorkflow/bpmn/parser/BpmnParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,13 @@ def add_bpmn_files(self, filenames):

def add_bpmn_io(self, file_like_object, filename=None):
"""
Add the given BPMN file like object to the parser's set.
Add the given BPMN file like object to the parser's set.
"""
self.add_bpmn_xml(etree.parse(file_like_object), filename)

def add_bpmn_str(self, bpmn_str, filename=None):
"""
Add the given BPMN string to the parser's set.
Add the given BPMN string to the parser's set.
"""
self.add_bpmn_xml(etree.fromstring(bpmn_str), filename)

Expand Down Expand Up @@ -366,8 +366,8 @@ def get_collaboration(self, name):
sp_spec = self.get_spec(process)
subprocesses[process] = sp_spec
subprocesses.update(self.get_subprocess_specs(process))
if len([s for s in sp_spec.task_specs.values() if
isinstance(s, StartEventMixin) and
if len([s for s in sp_spec.task_specs.values() if
isinstance(s, StartEventMixin) and
isinstance(s.event_definition, (NoneEventDefinition, TimerEventDefinition))
]):
participant = participant_type(spec, process, process)
Expand Down
10 changes: 5 additions & 5 deletions SpiffWorkflow/bpmn/serializer/helpers/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def to_dict(self, event_definition):
Arguments:
event_definition: the event definition
Returns:
dict: a dictionary representation of the event definition
"""
Expand Down Expand Up @@ -123,7 +123,7 @@ class TaskSpecConverter(BpmnConverter):
implement a converter for those task spec types. You'll need to implement the `to_dict` and
`from_dict` methods on any inheriting classes.
The default task spec converters are in the `default.task_spec` modules of this package; the
The default task spec converters are in the `default.task_spec` modules of this package; the
`camunda`,`dmn`, and `spiff` serialization packages contain other examples.
"""
def get_default_attributes(self, spec):
Expand Down Expand Up @@ -192,10 +192,10 @@ def get_standard_loop_attributes(self, spec):
'condition': spec.condition,
'test_before': spec.test_before,
}

def task_spec_from_dict(self, dct):
"""Creates a task spec based on the supplied dictionary.
It handles setting the default task spec attributes as well as attributes added by `BpmnSpecMixin`.
Arguments:
Expand All @@ -219,4 +219,4 @@ def task_spec_from_dict(self, dct):
# Ideally I'd fix it in the parser, but I'm afraid of quickly running into a wall there
spec.bpmn_id = bpmn_id

return spec
return spec
10 changes: 10 additions & 0 deletions SpiffWorkflow/spiff/parser/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
# 02110-1301 USA

import os
from SpiffWorkflow.bpmn.parser.ProcessParser import ProcessParser

from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator, full_tag
from SpiffWorkflow.spiff.specs.data_object import DataObject

from SpiffWorkflow.bpmn.specs.defaults import (
StartEvent,
Expand Down Expand Up @@ -65,9 +67,17 @@
SPIFF_XSD = os.path.join(os.path.dirname(__file__), 'schema', 'spiffworkflow.xsd')
VALIDATOR = BpmnValidator(imports={'spiffworkflow': SPIFF_XSD})

class SpiffProcessParser(ProcessParser):
def parse_data_object(self, obj):
extensions = SpiffTaskParser._parse_extensions(obj)
category = extensions.get('category')
return DataObject(category, obj.get('id'), obj.get('name'))


class SpiffBpmnParser(BpmnDmnParser):

PROCESS_PARSER_CLASS = SpiffProcessParser

OVERRIDE_PARSER_CLASSES = {
full_tag('task'): (SpiffTaskParser, NoneTask),
full_tag('userTask'): (SpiffTaskParser, UserTask),
Expand Down
7 changes: 6 additions & 1 deletion SpiffWorkflow/spiff/serializer/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
MessageEventDefinition as DefaultMessageEventDefinition,
SignalEventDefinition as DefaultSignalEventDefinition,
ErrorEventDefinition as DefaultErrorEventDefinition,
EscalationEventDefinition as DefaultEscalationEventDefinition,
EscalationEventDefinition as DefaultEscalationEventDefinition,
)

from SpiffWorkflow.spiff.specs.defaults import (
Expand Down Expand Up @@ -77,6 +77,9 @@
ItemAwareEventDefinitionConverter,
ErrorEscalationEventDefinitionConverter,
)
from SpiffWorkflow.bpmn.specs.data_spec import DataObject as DefaultDataObject
from SpiffWorkflow.spiff.specs.data_object import DataObject
from SpiffWorkflow.spiff.serializer.data_spec import DataObjectConverter

SPIFF_CONFIG = deepcopy(DEFAULT_CONFIG)

Expand All @@ -92,6 +95,7 @@
SPIFF_CONFIG.pop(DefaultStandardLoopTask)
SPIFF_CONFIG.pop(DefaultParallelMultiInstanceTask)
SPIFF_CONFIG.pop(DefaultSequentialMultiInstanceTask)
SPIFF_CONFIG.pop(DefaultDataObject)

SPIFF_CONFIG[NoneTask] = SpiffBpmnTaskConverter
SPIFF_CONFIG[ManualTask] = SpiffBpmnTaskConverter
Expand All @@ -110,3 +114,4 @@
SPIFF_CONFIG[ErrorEventDefinition] = ErrorEscalationEventDefinitionConverter
SPIFF_CONFIG[EscalationEventDefinition] = ErrorEscalationEventDefinitionConverter
SPIFF_CONFIG[BusinessRuleTask] = BusinessRuleTaskConverter
SPIFF_CONFIG[DataObject] = DataObjectConverter
7 changes: 7 additions & 0 deletions SpiffWorkflow/spiff/serializer/data_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from SpiffWorkflow.bpmn.serializer.helpers.spec import BpmnDataSpecificationConverter, EventDefinitionConverter

class DataObjectConverter(BpmnDataSpecificationConverter):
def to_dict(self, data_spec):
dct = super().to_dict(data_spec)
dct['category'] = data_spec.category
return dct
6 changes: 6 additions & 0 deletions SpiffWorkflow/spiff/specs/data_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from SpiffWorkflow.bpmn.specs.data_spec import DataObject as BpmnDataObject

class DataObject(BpmnDataObject):
def __init__(self, category, *args, **kwargs):
super().__init__(*args, **kwargs)
self.category = category
3 changes: 1 addition & 2 deletions tests/SpiffWorkflow/spiff/BusinessRuleTaskTest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow

from .BaseTestCase import BaseTestCase
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow

class BusinessRuleTaskTest(BaseTestCase):

Expand Down
160 changes: 160 additions & 0 deletions tests/SpiffWorkflow/spiff/data/data_object.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?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_19o7vxg" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.1" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
<bpmn:process id="Process" isExecutable="true">
<bpmn:dataObject id="obj_1" name="Object 1">
<bpmn:extensionElements>
<spiffworkflow:category>obj_1_category</spiffworkflow:category>
</bpmn:extensionElements>
</bpmn:dataObject>
<bpmn:dataObject id="obj_2" name="Object 2" />
<bpmn:startEvent id="Event_0kmwi7u">
<bpmn:outgoing>Flow_18858hr</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_18858hr" sourceRef="Event_0kmwi7u" targetRef="generate_data" />
<bpmn:sequenceFlow id="Flow_0gbxq9s" sourceRef="generate_data" targetRef="task_1" />
<bpmn:sequenceFlow id="Flow_1r7v9yo" sourceRef="task_1" targetRef="read_data" />
<bpmn:dataObjectReference id="DataObjectReference_17fhr1j" name="Data" dataObjectRef="obj_1" />
<bpmn:dataObjectReference id="DataObjectReference_0pztwm3" name="Data" dataObjectRef="obj_1" />
<bpmn:dataObjectReference id="DataObjectReference_0cm8dnh" name="Data" dataObjectRef="obj_1" />
<bpmn:dataObjectReference id="DataObjectReference_1dn9eoi" name="Data" dataObjectRef="obj_2" />
<bpmn:endEvent id="Event_0qw1yr0">
<bpmn:incoming>Flow_19pyf8s</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1tnu3ej" sourceRef="read_data" targetRef="subprocess" />
<bpmn:userTask id="read_data" name="Read Data">
<bpmn:incoming>Flow_1r7v9yo</bpmn:incoming>
<bpmn:outgoing>Flow_1tnu3ej</bpmn:outgoing>
<bpmn:property id="Property_1uusomz" name="__targetRef_placeholder" />
<bpmn:dataInputAssociation id="DataInputAssociation_1vaag83">
<bpmn:sourceRef>DataObjectReference_0pztwm3</bpmn:sourceRef>
<bpmn:targetRef>Property_1uusomz</bpmn:targetRef>
</bpmn:dataInputAssociation>
</bpmn:userTask>
<bpmn:userTask id="generate_data" name="Generate Data">
<bpmn:incoming>Flow_18858hr</bpmn:incoming>
<bpmn:outgoing>Flow_0gbxq9s</bpmn:outgoing>
<bpmn:dataOutputAssociation id="DataOutputAssociation_053pozp">
<bpmn:targetRef>DataObjectReference_17fhr1j</bpmn:targetRef>
</bpmn:dataOutputAssociation>
</bpmn:userTask>
<bpmn:userTask id="task_1" name="Task">
<bpmn:incoming>Flow_0gbxq9s</bpmn:incoming>
<bpmn:outgoing>Flow_1r7v9yo</bpmn:outgoing>
</bpmn:userTask>
<bpmn:subProcess id="subprocess" name="Subprocess">
<bpmn:incoming>Flow_1tnu3ej</bpmn:incoming>
<bpmn:outgoing>Flow_19pyf8s</bpmn:outgoing>
<bpmn:startEvent id="Event_1wuwx2f">
<bpmn:outgoing>Flow_0yx8lkz</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="placeholder">
<bpmn:incoming>Flow_0yx8lkz</bpmn:incoming>
<bpmn:outgoing>Flow_0rk4i35</bpmn:outgoing>
<bpmn:property id="Property_1q5wp77" name="__targetRef_placeholder" />
<bpmn:dataInputAssociation id="DataInputAssociation_0w2qahx">
<bpmn:sourceRef>DataObjectReference_0cm8dnh</bpmn:sourceRef>
<bpmn:targetRef>Property_1q5wp77</bpmn:targetRef>
</bpmn:dataInputAssociation>
<bpmn:dataOutputAssociation id="DataOutputAssociation_164qpaq">
<bpmn:targetRef>DataObjectReference_1dn9eoi</bpmn:targetRef>
</bpmn:dataOutputAssociation>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_0yx8lkz" sourceRef="Event_1wuwx2f" targetRef="placeholder" />
<bpmn:endEvent id="Event_1qcnmnt">
<bpmn:incoming>Flow_0rk4i35</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0rk4i35" sourceRef="placeholder" targetRef="Event_1qcnmnt" />
</bpmn:subProcess>
<bpmn:sequenceFlow id="Flow_19pyf8s" sourceRef="subprocess" targetRef="Event_0qw1yr0" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process">
<bpmndi:BPMNEdge id="Flow_19pyf8s_di" bpmnElement="Flow_19pyf8s">
<di:waypoint x="1110" y="180" />
<di:waypoint x="1192" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1tnu3ej_di" bpmnElement="Flow_1tnu3ej">
<di:waypoint x="680" y="180" />
<di:waypoint x="740" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1r7v9yo_di" bpmnElement="Flow_1r7v9yo">
<di:waypoint x="520" y="180" />
<di:waypoint x="580" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0gbxq9s_di" bpmnElement="Flow_0gbxq9s">
<di:waypoint x="360" y="180" />
<di:waypoint x="420" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_18858hr_di" bpmnElement="Flow_18858hr">
<di:waypoint x="208" y="180" />
<di:waypoint x="260" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_0kmwi7u_di" bpmnElement="Event_0kmwi7u">
<dc:Bounds x="172" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_17fhr1j_di" bpmnElement="DataObjectReference_17fhr1j">
<dc:Bounds x="292" y="275" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="299" y="332" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_0pztwm3_di" bpmnElement="DataObjectReference_0pztwm3">
<dc:Bounds x="612" y="275" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="619" y="332" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_0cm8dnh_di" bpmnElement="DataObjectReference_0cm8dnh">
<dc:Bounds x="907" y="375" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="913" y="432" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0qw1yr0_di" bpmnElement="Event_0qw1yr0">
<dc:Bounds x="1192" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_08lb08m_di" bpmnElement="read_data">
<dc:Bounds x="580" y="140" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_00pwxgv_di" bpmnElement="generate_data">
<dc:Bounds x="260" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1xmp3i1_di" bpmnElement="task_1">
<dc:Bounds x="420" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_10c32lr_di" bpmnElement="subprocess" isExpanded="true">
<dc:Bounds x="740" y="80" width="370" height="200" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0rk4i35_di" bpmnElement="Flow_0rk4i35">
<di:waypoint x="970" y="180" />
<di:waypoint x="1032" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0yx8lkz_di" bpmnElement="Flow_0yx8lkz">
<di:waypoint x="816" y="180" />
<di:waypoint x="870" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_1wuwx2f_di" bpmnElement="Event_1wuwx2f">
<dc:Bounds x="780" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_01ooqcb_di" bpmnElement="placeholder">
<dc:Bounds x="870" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1qcnmnt_di" bpmnElement="Event_1qcnmnt">
<dc:Bounds x="1032" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="DataInputAssociation_1vaag83_di" bpmnElement="DataInputAssociation_1vaag83">
<di:waypoint x="630" y="275" />
<di:waypoint x="630" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="DataOutputAssociation_053pozp_di" bpmnElement="DataOutputAssociation_053pozp">
<di:waypoint x="309" y="220" />
<di:waypoint x="308" y="275" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="DataInputAssociation_0w2qahx_di" bpmnElement="DataInputAssociation_0w2qahx">
<di:waypoint x="925" y="375" />
<di:waypoint x="925" y="280" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
14 changes: 14 additions & 0 deletions tests/SpiffWorkflow/spiff/data_object_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .BaseTestCase import BaseTestCase
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow


class DataObjectTest(BaseTestCase):

def setUp(self):
self.spec, self.subprocesses = self.load_workflow_spec('data_object.bpmn', 'Process')

def test_can_get_category_from_data_object(self):
self.workflow = BpmnWorkflow(self.spec, self.subprocesses)
category = self.workflow.spec.data_objects['obj_1'].category
self.assertEqual(category, 'obj_1_category')
self.save_restore()

0 comments on commit e4ceff4

Please sign in to comment.