mirror of
https://github.com/sartography/spiffworkflow-backend.git
synced 2025-02-24 13:28:31 +00:00
Merge pull request #86 from sartography/feature/call_actitity
Feature/call actitity
This commit is contained in:
commit
79bd9a5853
@ -1,8 +1,8 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: e16389841ca6
|
||||
Revision ID: 240bdce32a9f
|
||||
Revises:
|
||||
Create Date: 2022-09-07 11:41:16.981763
|
||||
Create Date: 2022-09-08 12:49:51.609196
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e16389841ca6'
|
||||
revision = '240bdce32a9f'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@ -25,6 +25,13 @@ def upgrade():
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('token')
|
||||
)
|
||||
op.create_table('bpmn_process_id_lookup',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('bpmn_process_identifier', sa.String(length=50), nullable=True),
|
||||
sa.Column('bpmn_file_relative_path', sa.String(length=255), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), 'bpmn_process_id_lookup', ['bpmn_process_identifier'], unique=True)
|
||||
op.create_table('group',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=True),
|
||||
@ -290,5 +297,7 @@ def downgrade():
|
||||
op.drop_index(op.f('ix_message_model_identifier'), table_name='message_model')
|
||||
op.drop_table('message_model')
|
||||
op.drop_table('group')
|
||||
op.drop_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), table_name='bpmn_process_id_lookup')
|
||||
op.drop_table('bpmn_process_id_lookup')
|
||||
op.drop_table('admin_session')
|
||||
# ### end Alembic commands ###
|
4
poetry.lock
generated
4
poetry.lock
generated
@ -1847,7 +1847,7 @@ pytz = "*"
|
||||
type = "git"
|
||||
url = "https://github.com/sartography/SpiffWorkflow"
|
||||
reference = "main"
|
||||
resolved_reference = "776b2724255a51f9cb9497ff922768fdc80b03da"
|
||||
resolved_reference = "ecd01f20a0d7142115f4ac66ccef341fcf2b176f"
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
@ -2157,7 +2157,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "3fe7680583608ddd4ea93082b0c6c250507b53b2211218e00b2df01649bd6c6b"
|
||||
content-hash = "7a3c07a2eef00685adbf44b6e26b740e20fc52bf85e916b6c171b13d4fcc6dc9"
|
||||
|
||||
[metadata.files]
|
||||
alabaster = [
|
||||
|
@ -27,9 +27,9 @@ flask-marshmallow = "*"
|
||||
flask-migrate = "*"
|
||||
flask-restful = "*"
|
||||
werkzeug = "*"
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
|
||||
# spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "feature/centralized-logging"}
|
||||
# spiffworkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
|
||||
SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
|
||||
# SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "feature/dependencies"}
|
||||
# SpiffWorkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
|
||||
sentry-sdk = "1.9.0"
|
||||
sphinx-autoapi = "^1.8.4"
|
||||
# flask-bpmn = {develop = true, path = "/home/jason/projects/github/sartography/flask-bpmn"}
|
||||
|
@ -30,3 +30,7 @@ OPEN_ID_REALM_NAME = environ.get("OPEN_ID_REALM_NAME", default="spiffworkflow")
|
||||
OPEN_ID_CLIENT_SECRET_KEY = environ.get(
|
||||
"OPEN_ID_CLIENT_SECRET_KEY", default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q"
|
||||
) # noqa: S105
|
||||
|
||||
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
|
||||
environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="false") == "false"
|
||||
)
|
||||
|
@ -1,4 +1,9 @@
|
||||
"""Testing.py."""
|
||||
from os import environ
|
||||
|
||||
|
||||
TESTING = True
|
||||
SECRET_KEY = "the_secret_key"
|
||||
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
|
||||
environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="true") == "true"
|
||||
)
|
||||
|
@ -5,6 +5,9 @@ autoflake8 will remove these lines without the noqa comment
|
||||
from flask_bpmn.models.db import add_listeners
|
||||
|
||||
from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import (
|
||||
BpmnProcessIdLookup,
|
||||
) # noqa: F401
|
||||
from spiffworkflow_backend.models.data_store import DataStoreModel # noqa: F401
|
||||
from spiffworkflow_backend.models.file import FileModel # noqa: F401
|
||||
from spiffworkflow_backend.models.message_correlation_property import (
|
||||
|
13
src/spiffworkflow_backend/models/bpmn_process_id_lookup.py
Normal file
13
src/spiffworkflow_backend/models/bpmn_process_id_lookup.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""Message_model."""
|
||||
from flask_bpmn.models.db import db
|
||||
from flask_bpmn.models.db import SpiffworkflowBaseDBModel
|
||||
|
||||
|
||||
class BpmnProcessIdLookup(SpiffworkflowBaseDBModel):
|
||||
"""BpmnProcessIdLookup."""
|
||||
|
||||
__tablename__ = "bpmn_process_id_lookup"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
bpmn_process_identifier = db.Column(db.String(50), unique=True, index=True)
|
||||
bpmn_file_relative_path = db.Column(db.String(255))
|
@ -277,7 +277,9 @@ def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Res
|
||||
file.process_model_id = process_model.id
|
||||
file.process_group_id = process_model.process_group_id
|
||||
if not process_model.primary_process_id and file.type == FileType.bpmn.value:
|
||||
SpecFileService.set_primary_bpmn(process_model, file.name)
|
||||
SpecFileService.process_bpmn_file(
|
||||
process_model, file.name, set_primary_file=True
|
||||
)
|
||||
process_model_service.save_process_model(process_model)
|
||||
return Response(
|
||||
json.dumps(FileSchema().dump(file)), status=201, mimetype="application/json"
|
||||
|
@ -48,6 +48,21 @@ class FileSystemService:
|
||||
FileSystemService.root_path(), FileSystemService.LIBRARY_SPECS, name
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def full_path_from_relative_path(relative_path: str) -> str:
|
||||
"""Full_path_from_relative_path."""
|
||||
return os.path.join(FileSystemService.root_path(), relative_path)
|
||||
|
||||
@staticmethod
|
||||
def process_model_relative_path(spec: ProcessModelInfo) -> str:
|
||||
"""Get the file path to a process model relative to BPMN_SPEC_ABSOLUTE_DIR.
|
||||
|
||||
If the full path is /path/to/process-group-a/group-b/process-model-a, it will return:
|
||||
process-group-a/group-b/process-model-a
|
||||
"""
|
||||
workflow_path = FileSystemService.workflow_path(spec)
|
||||
return os.path.relpath(workflow_path, start=FileSystemService.root_path())
|
||||
|
||||
@staticmethod
|
||||
def process_group_path_for_spec(spec: ProcessModelInfo) -> str:
|
||||
"""Category_path_for_spec."""
|
||||
|
@ -109,11 +109,6 @@ def setup_logger(app: Flask) -> None:
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
log_level = logging.DEBUG
|
||||
log_formatter = logging.Formatter(
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
# the json formatter is nice for real environments but makes
|
||||
# debugging locally a little more difficult
|
||||
if app.env != "development":
|
||||
@ -131,25 +126,31 @@ def setup_logger(app: Flask) -> None:
|
||||
)
|
||||
log_formatter = json_formatter
|
||||
|
||||
spiff_logger_filehandler = None
|
||||
if app.config["SPIFFWORKFLOW_BACKEND_LOG_TO_FILE"]:
|
||||
spiff_logger_filehandler = logging.FileHandler(f"log/{app.env}.log")
|
||||
spiff_logger_filehandler.setLevel(logging.DEBUG)
|
||||
spiff_logger_filehandler.setFormatter(log_formatter)
|
||||
|
||||
# make all loggers act the same
|
||||
for name in logging.root.manager.loggerDict:
|
||||
if "spiff" not in name:
|
||||
the_logger = logging.getLogger(name)
|
||||
the_logger.setLevel(log_level)
|
||||
for the_handler in the_logger.handlers:
|
||||
the_handler.setFormatter(log_formatter)
|
||||
the_handler.setLevel(log_level)
|
||||
if spiff_logger_filehandler:
|
||||
the_logger.handlers = []
|
||||
the_logger.propagate = False
|
||||
the_logger.addHandler(spiff_logger_filehandler)
|
||||
else:
|
||||
for the_handler in the_logger.handlers:
|
||||
the_handler.setFormatter(log_formatter)
|
||||
the_handler.setLevel(log_level)
|
||||
|
||||
spiff_logger = logging.getLogger("spiff")
|
||||
spiff_logger.setLevel(logging.DEBUG)
|
||||
# spiff_logger_handler = logging.StreamHandler(sys.stdout)
|
||||
spiff_formatter = logging.Formatter(
|
||||
"%(asctime)s | %(levelname)s | %(message)s | %(action)s | %(task_type)s | %(process)s | %(processName)s | %(process_instance_id)s"
|
||||
)
|
||||
# spiff_logger_handler.setFormatter(spiff_formatter)
|
||||
# fh = logging.FileHandler('test.log')
|
||||
# spiff_logger_handler.setLevel(logging.DEBUG)
|
||||
# spiff_logger.addHandler(spiff_logger_handler)
|
||||
|
||||
# if you add a handler to spiff, it will be used/inherited by spiff.metrics
|
||||
# if you add a filter to the spiff logger directly (and not the handler), it will NOT be inherited by spiff.metrics
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Process_instance_processor."""
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
@ -47,6 +48,7 @@ from SpiffWorkflow.spiff.serializer import UserTaskConverter
|
||||
from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
|
||||
|
||||
from spiffworkflow_backend.models.active_task import ActiveTaskModel
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
|
||||
from spiffworkflow_backend.models.file import File
|
||||
from spiffworkflow_backend.models.file import FileType
|
||||
from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel
|
||||
@ -65,6 +67,7 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.task_event import TaskAction
|
||||
from spiffworkflow_backend.models.task_event import TaskEventModel
|
||||
from spiffworkflow_backend.models.user import UserModelSchema
|
||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||
from spiffworkflow_backend.services.user_service import UserService
|
||||
@ -449,6 +452,42 @@ class ProcessInstanceProcessor:
|
||||
parser = MyCustomParser()
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def find_required_files(
|
||||
bpmn_file_full_path: str,
|
||||
parser: BpmnDmnParser,
|
||||
processed_identifiers: Optional[set[str]] = None,
|
||||
) -> None:
|
||||
"""Find_required_files."""
|
||||
if processed_identifiers is None:
|
||||
processed_identifiers = set()
|
||||
parser.get_dependencies()
|
||||
processor_dependencies = parser.get_process_dependencies()
|
||||
processor_dependencies_new = processor_dependencies - processed_identifiers
|
||||
|
||||
new_bpmn_files = set()
|
||||
for bpmn_process_identifier in processor_dependencies_new:
|
||||
bpmn_process_id_lookup = BpmnProcessIdLookup.query.filter_by(
|
||||
bpmn_process_identifier=bpmn_process_identifier
|
||||
).first()
|
||||
new_bpmn_file_full_path = None
|
||||
if bpmn_process_id_lookup is None:
|
||||
# TODO: this should only happen rarely
|
||||
new_bpmn_file_full_path = ""
|
||||
else:
|
||||
new_bpmn_file_full_path = os.path.join(
|
||||
FileSystemService.root_path(),
|
||||
bpmn_process_id_lookup.bpmn_file_relative_path,
|
||||
)
|
||||
new_bpmn_files.add(new_bpmn_file_full_path)
|
||||
processed_identifiers.add(bpmn_process_identifier)
|
||||
|
||||
for new_bpmn_file_full_path in new_bpmn_files:
|
||||
parser.add_bpmn_file(new_bpmn_file_full_path)
|
||||
ProcessInstanceProcessor.find_required_files(
|
||||
new_bpmn_file_full_path, parser, processed_identifiers
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_spec(
|
||||
files: List[File], process_model_info: ProcessModelInfo
|
||||
@ -475,6 +514,13 @@ class ProcessInstanceProcessor:
|
||||
% process_model_info.id,
|
||||
)
|
||||
)
|
||||
|
||||
workflow_path = FileSystemService.workflow_path(process_model_info) or ""
|
||||
primary_file_full_path = os.path.join(
|
||||
workflow_path, (process_model_info.primary_file_name or "")
|
||||
)
|
||||
ProcessInstanceProcessor.find_required_files(primary_file_full_path, parser)
|
||||
|
||||
try:
|
||||
spec = parser.get_spec(process_model_info.primary_process_id)
|
||||
|
||||
|
@ -12,6 +12,7 @@ from lxml.etree import _Element # type: ignore
|
||||
from lxml.etree import Element as EtreeElement
|
||||
from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore
|
||||
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
|
||||
from spiffworkflow_backend.models.file import File
|
||||
from spiffworkflow_backend.models.file import FileType
|
||||
from spiffworkflow_backend.models.message_correlation_property import (
|
||||
@ -72,13 +73,21 @@ class SpecFileService(FileSystemService):
|
||||
file_path = SpecFileService.file_path(process_model_info, file_name)
|
||||
SpecFileService.write_file_data_to_system(file_path, binary_data)
|
||||
file = SpecFileService.to_file_object(file_name, file_path)
|
||||
if file_name == process_model_info.primary_file_name:
|
||||
SpecFileService.set_primary_bpmn(process_model_info, file_name, binary_data)
|
||||
elif process_model_info.primary_file_name is None and file.type == str(
|
||||
FileType.bpmn
|
||||
):
|
||||
# If no primary process exists, make this pirmary process.
|
||||
SpecFileService.set_primary_bpmn(process_model_info, file_name, binary_data)
|
||||
|
||||
if file.type == str(FileType.bpmn):
|
||||
set_primary_file = False
|
||||
if (
|
||||
process_model_info.primary_file_name is None
|
||||
or file_name == process_model_info.primary_file_name
|
||||
):
|
||||
# If no primary process exists, make this primary process.
|
||||
set_primary_file = True
|
||||
SpecFileService.process_bpmn_file(
|
||||
process_model_info,
|
||||
file_name,
|
||||
binary_data,
|
||||
set_primary_file=set_primary_file,
|
||||
)
|
||||
|
||||
return file
|
||||
|
||||
@ -138,10 +147,11 @@ class SpecFileService(FileSystemService):
|
||||
shutil.rmtree(dir_path)
|
||||
|
||||
@staticmethod
|
||||
def set_primary_bpmn(
|
||||
def process_bpmn_file(
|
||||
process_model_info: ProcessModelInfo,
|
||||
file_name: str,
|
||||
binary_data: Optional[bytes] = None,
|
||||
set_primary_file: Optional[bool] = False,
|
||||
) -> None:
|
||||
"""Set_primary_bpmn."""
|
||||
# If this is a BPMN, extract the process id, and determine if it is contains swim lanes.
|
||||
@ -151,13 +161,23 @@ class SpecFileService(FileSystemService):
|
||||
if not binary_data:
|
||||
binary_data = SpecFileService.get_data(process_model_info, file_name)
|
||||
try:
|
||||
bpmn: EtreeElement = etree.fromstring(binary_data)
|
||||
process_model_info.primary_process_id = SpecFileService.get_process_id(
|
||||
bpmn
|
||||
bpmn_etree_element: EtreeElement = etree.fromstring(binary_data)
|
||||
|
||||
if set_primary_file:
|
||||
process_model_info.primary_process_id = (
|
||||
SpecFileService.get_process_id(bpmn_etree_element)
|
||||
)
|
||||
process_model_info.primary_file_name = file_name
|
||||
process_model_info.is_review = SpecFileService.has_swimlane(
|
||||
bpmn_etree_element
|
||||
)
|
||||
|
||||
SpecFileService.check_for_message_models(
|
||||
bpmn_etree_element, process_model_info
|
||||
)
|
||||
SpecFileService.store_process_ids(
|
||||
process_model_info, file_name, bpmn_etree_element
|
||||
)
|
||||
process_model_info.primary_file_name = file_name
|
||||
process_model_info.is_review = SpecFileService.has_swimlane(bpmn)
|
||||
SpecFileService.check_for_message_models(bpmn, process_model_info)
|
||||
|
||||
except etree.XMLSyntaxError as xse:
|
||||
raise ApiError(
|
||||
@ -197,8 +217,8 @@ class SpecFileService(FileSystemService):
|
||||
return retval
|
||||
|
||||
@staticmethod
|
||||
def get_process_id(et_root: _Element) -> str:
|
||||
"""Get_process_id."""
|
||||
def get_executable_process_elements(et_root: _Element) -> list[_Element]:
|
||||
"""Get_executable_process_elements."""
|
||||
process_elements = []
|
||||
for child in et_root:
|
||||
if child.tag.endswith("process") and child.attrib.get(
|
||||
@ -208,6 +228,19 @@ class SpecFileService(FileSystemService):
|
||||
|
||||
if len(process_elements) == 0:
|
||||
raise ValidationException("No executable process tag found")
|
||||
return process_elements
|
||||
|
||||
@staticmethod
|
||||
def get_executable_process_ids(et_root: _Element) -> list[str]:
|
||||
"""Get_executable_process_ids."""
|
||||
process_elements = SpecFileService.get_executable_process_elements(et_root)
|
||||
process_ids = [pe.attrib["id"] for pe in process_elements]
|
||||
return process_ids
|
||||
|
||||
@staticmethod
|
||||
def get_process_id(et_root: _Element) -> str:
|
||||
"""Get_process_id."""
|
||||
process_elements = SpecFileService.get_executable_process_elements(et_root)
|
||||
|
||||
# There are multiple root elements
|
||||
if len(process_elements) > 1:
|
||||
@ -226,6 +259,48 @@ class SpecFileService(FileSystemService):
|
||||
|
||||
return str(process_elements[0].attrib["id"])
|
||||
|
||||
@staticmethod
|
||||
def store_process_ids(
|
||||
process_model_info: ProcessModelInfo, bpmn_file_name: str, et_root: _Element
|
||||
) -> None:
|
||||
"""Store_process_ids."""
|
||||
relative_process_model_path = SpecFileService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
relative_bpmn_file_path = os.path.join(
|
||||
relative_process_model_path, bpmn_file_name
|
||||
)
|
||||
process_ids = SpecFileService.get_executable_process_ids(et_root)
|
||||
for process_id in process_ids:
|
||||
process_id_lookup = BpmnProcessIdLookup.query.filter_by(
|
||||
bpmn_process_identifier=process_id
|
||||
).first()
|
||||
if process_id_lookup is None:
|
||||
process_id_lookup = BpmnProcessIdLookup(
|
||||
bpmn_process_identifier=process_id,
|
||||
bpmn_file_relative_path=relative_bpmn_file_path,
|
||||
)
|
||||
db.session.add(process_id_lookup)
|
||||
db.session.commit()
|
||||
else:
|
||||
if relative_bpmn_file_path != process_id_lookup.bpmn_file_relative_path:
|
||||
full_bpmn_file_path = SpecFileService.full_path_from_relative_path(
|
||||
process_id_lookup.bpmn_file_relative_path
|
||||
)
|
||||
# if the old relative bpmn file no longer exists, then assume things were moved around
|
||||
# on the file system. Otherwise, assume it is a duplicate process id and error.
|
||||
if os.path.isfile(full_bpmn_file_path):
|
||||
raise ValidationException(
|
||||
f"Process id ({process_id}) has already been used for "
|
||||
f"{process_id_lookup.bpmn_file_relative_path}. It cannot be reused."
|
||||
)
|
||||
else:
|
||||
process_id_lookup.bpmn_file_relative_path = (
|
||||
relative_bpmn_file_path
|
||||
)
|
||||
db.session.add(process_id_lookup)
|
||||
db.session.commit()
|
||||
|
||||
@staticmethod
|
||||
def check_for_message_models(
|
||||
et_root: _Element, process_model_info: ProcessModelInfo
|
||||
|
55
tests/data/call_activity_nested/call_activity_level_2.bpmn
Normal file
55
tests/data/call_activity_nested/call_activity_level_2.bpmn
Normal file
@ -0,0 +1,55 @@
|
||||
<?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" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Level2" name="Level 2" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="level3" />
|
||||
<bpmn:callActivity id="level3" name="call level 3" calledElement="Level3">
|
||||
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="level3" targetRef="level2b_second_call" />
|
||||
<bpmn:endEvent id="Event_18dla68">
|
||||
<bpmn:documentation># Main Workflow
|
||||
Hello {{my_other_var}}
|
||||
|
||||
</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_1ll6j9j</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1ll6j9j" sourceRef="level2b_second_call" targetRef="Event_18dla68" />
|
||||
<bpmn:callActivity id="level2b_second_call" name="call level 2b again" calledElement="Level2b">
|
||||
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1ll6j9j</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level2">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="level3">
|
||||
<dc:Bounds x="280" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
|
||||
<dc:Bounds x="552" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0522m2j_di" bpmnElement="level2b_second_call">
|
||||
<dc:Bounds x="430" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="280" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
|
||||
<di:waypoint x="380" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1ll6j9j_di" bpmnElement="Flow_1ll6j9j">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="552" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
44
tests/data/call_activity_nested/call_activity_level_2b.bpmn
Normal file
44
tests/data/call_activity_nested/call_activity_level_2b.bpmn
Normal file
@ -0,0 +1,44 @@
|
||||
<?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" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Level2b" name="Level 2b" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="do_nothing" />
|
||||
<bpmn:endEvent id="Event_18dla68">
|
||||
<bpmn:documentation># Main Workflow
|
||||
Hello {{my_other_var}}
|
||||
|
||||
</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0l0w6u9</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0l0w6u9" sourceRef="do_nothing" targetRef="Event_18dla68" />
|
||||
<bpmn:scriptTask id="do_nothing" name="Do Nothing">
|
||||
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0l0w6u9</bpmn:outgoing>
|
||||
<bpmn:script>a = 1</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level2b">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
|
||||
<dc:Bounds x="432" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1reqred_di" bpmnElement="do_nothing">
|
||||
<dc:Bounds x="260" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="260" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0l0w6u9_di" bpmnElement="Flow_0l0w6u9">
|
||||
<di:waypoint x="360" y="117" />
|
||||
<di:waypoint x="432" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
43
tests/data/call_activity_nested/call_activity_level_3.bpmn
Normal file
43
tests/data/call_activity_nested/call_activity_level_3.bpmn
Normal file
@ -0,0 +1,43 @@
|
||||
<?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" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Level3" name="Level 3" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="do_nothing" />
|
||||
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="do_nothing" targetRef="Event_18dla68" />
|
||||
<bpmn:endEvent id="Event_18dla68">
|
||||
<bpmn:documentation># Main Workflow
|
||||
Hello {{my_other_var}}
|
||||
|
||||
</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:scriptTask id="do_nothing" name="Do Nothing">
|
||||
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
|
||||
<bpmn:script>a = 3</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level3">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
|
||||
<dc:Bounds x="432" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1po21cu_di" bpmnElement="do_nothing">
|
||||
<dc:Bounds x="280" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="280" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
|
||||
<di:waypoint x="380" y="117" />
|
||||
<di:waypoint x="432" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
55
tests/data/call_activity_nested/call_activity_nested.bpmn
Normal file
55
tests/data/call_activity_nested/call_activity_nested.bpmn
Normal file
@ -0,0 +1,55 @@
|
||||
<?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:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Level1" name="Level1" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="Activity_12zat0d" />
|
||||
<bpmn:callActivity id="Activity_12zat0d" name="call level 2" calledElement="Level2">
|
||||
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="Activity_12zat0d" targetRef="Activity_0rkbhbz" />
|
||||
<bpmn:endEvent id="Event_18dla68">
|
||||
<bpmn:documentation># Main Workflow
|
||||
Hello {{my_other_var}}
|
||||
|
||||
</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0upce00</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0upce00" sourceRef="Activity_0rkbhbz" targetRef="Event_18dla68" />
|
||||
<bpmn:callActivity id="Activity_0rkbhbz" name="call level 2B" calledElement="Level2b">
|
||||
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0upce00</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level1">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="Activity_12zat0d">
|
||||
<dc:Bounds x="280" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
|
||||
<dc:Bounds x="702" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0jddvat_di" bpmnElement="Activity_0rkbhbz">
|
||||
<dc:Bounds x="420" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="280" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
|
||||
<di:waypoint x="380" y="117" />
|
||||
<di:waypoint x="420" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0upce00_di" bpmnElement="Flow_0upce00">
|
||||
<di:waypoint x="520" y="117" />
|
||||
<di:waypoint x="702" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
@ -0,0 +1,72 @@
|
||||
<?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:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Level1" name="Level1" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="Activity_12zat0d" />
|
||||
<bpmn:callActivity id="Activity_12zat0d" name="call level 2" calledElement="Level2">
|
||||
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="Activity_12zat0d" targetRef="Activity_0rkbhbz" />
|
||||
<bpmn:endEvent id="Event_18dla68">
|
||||
<bpmn:documentation># Main Workflow
|
||||
Hello {{my_other_var}}
|
||||
|
||||
</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_04o2npf</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0upce00" sourceRef="Activity_0rkbhbz" targetRef="Activity_0gg4414" />
|
||||
<bpmn:callActivity id="Activity_0rkbhbz" name="call level 2B" calledElement="Level2b">
|
||||
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0upce00</bpmn:outgoing>
|
||||
</bpmn:callActivity>
|
||||
<bpmn:sequenceFlow id="Flow_04o2npf" sourceRef="Activity_0gg4414" targetRef="Event_18dla68" />
|
||||
<bpmn:businessRuleTask id="Activity_0gg4414" name="call level 2c" camunda:decisionRef="Level2c">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:calledDecisionId>Level2c</spiffworkflow:calledDecisionId>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_0upce00</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_04o2npf</bpmn:outgoing>
|
||||
</bpmn:businessRuleTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level1">
|
||||
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
|
||||
<di:waypoint x="380" y="117" />
|
||||
<di:waypoint x="420" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="280" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0upce00_di" bpmnElement="Flow_0upce00">
|
||||
<di:waypoint x="520" y="117" />
|
||||
<di:waypoint x="560" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_04o2npf_di" bpmnElement="Flow_04o2npf">
|
||||
<di:waypoint x="660" y="117" />
|
||||
<di:waypoint x="702" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="Activity_12zat0d">
|
||||
<dc:Bounds x="280" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0jddvat_di" bpmnElement="Activity_0rkbhbz">
|
||||
<dc:Bounds x="420" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
|
||||
<dc:Bounds x="702" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1lzid7b_di" bpmnElement="Activity_0gg4414">
|
||||
<dc:Bounds x="560" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
20
tests/data/call_activity_nested/level2c.dmn
Normal file
20
tests/data/call_activity_nested/level2c.dmn
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/" xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/" xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Level2c" name="DRD" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.0.0">
|
||||
<decision id="Decision_0vrtcmk" name="Decision 1">
|
||||
<decisionTable id="DecisionTable_1gamsry">
|
||||
<input id="Input_1">
|
||||
<inputExpression id="InputExpression_1" typeRef="string">
|
||||
<text></text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="Output_1" typeRef="string" />
|
||||
</decisionTable>
|
||||
</decision>
|
||||
<dmndi:DMNDI>
|
||||
<dmndi:DMNDiagram>
|
||||
<dmndi:DMNShape dmnElementRef="Decision_0vrtcmk">
|
||||
<dc:Bounds height="80" width="180" x="160" y="100" />
|
||||
</dmndi:DMNShape>
|
||||
</dmndi:DMNDiagram>
|
||||
</dmndi:DMNDI>
|
||||
</definitions>
|
@ -1,7 +1,7 @@
|
||||
<?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" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||
<bpmn:collaboration id="Collaboration_0oye1os">
|
||||
<bpmn:participant id="message_receiver_one" name="Message Receiver" processRef="message_receiver_process" />
|
||||
<bpmn:participant id="message_receiver_one" name="Message Receiver" processRef="message_receiver_process_one" />
|
||||
<bpmn:participant id="message_sender" name="Message Sender" />
|
||||
<bpmn:messageFlow id="message_send_flow" name="Message Send Flow" sourceRef="message_sender" targetRef="receive_message" />
|
||||
<bpmn:messageFlow id="Flow_0ds946g" sourceRef="send_message_response" targetRef="message_sender" />
|
||||
@ -40,7 +40,7 @@
|
||||
}</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:process id="message_receiver_process" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:process id="message_receiver_process_one" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
|
||||
<bpmn:endEvent id="Event_0q5otqd">
|
||||
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?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" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||
<bpmn:collaboration id="Collaboration_0oye1os">
|
||||
<bpmn:participant id="message_receiver_two" name="Message Receiver" processRef="message_receiver_process" />
|
||||
<bpmn:participant id="message_receiver_two" name="Message Receiver" processRef="message_receiver_process_two" />
|
||||
<bpmn:participant id="message_sender" name="Message Sender" />
|
||||
<bpmn:messageFlow id="message_send_flow" name="Message Send Flow" sourceRef="message_sender" targetRef="receive_message" />
|
||||
<bpmn:messageFlow id="Flow_0ds946g" sourceRef="send_message_response" targetRef="message_sender" />
|
||||
@ -40,7 +40,7 @@
|
||||
}</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:process id="message_receiver_process" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:process id="message_receiver_process_two" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
|
||||
<bpmn:endEvent id="Event_0q5otqd">
|
||||
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>
|
||||
|
@ -216,7 +216,7 @@ class BaseTest:
|
||||
# return public_access_token
|
||||
|
||||
def create_process_instance_from_process_model(
|
||||
self, process_model: ProcessModelInfo, status: str
|
||||
self, process_model: ProcessModelInfo, status: Optional[str] = "not_started"
|
||||
) -> ProcessInstanceModel:
|
||||
"""Create_process_instance_from_process_model."""
|
||||
user = self.find_or_create_user()
|
||||
|
@ -90,6 +90,7 @@ class ExampleDataLoader:
|
||||
continue # Don't try to process sub directories
|
||||
|
||||
filename = os.path.basename(file_path)
|
||||
# since there are multiple bpmn files in a test data directory, ensure we set the correct one as the primary
|
||||
is_primary = filename.lower() == bpmn_file_name_with_extension
|
||||
file = None
|
||||
try:
|
||||
@ -99,12 +100,11 @@ class ExampleDataLoader:
|
||||
process_model_info=spec, file_name=filename, binary_data=data
|
||||
)
|
||||
if is_primary:
|
||||
SpecFileService.set_primary_bpmn(spec, filename, data)
|
||||
SpecFileService.process_bpmn_file(
|
||||
spec, filename, data, set_primary_file=True
|
||||
)
|
||||
workflow_spec_service = ProcessModelService()
|
||||
workflow_spec_service.save_process_model(spec)
|
||||
except IsADirectoryError:
|
||||
# Ignore sub directories
|
||||
pass
|
||||
finally:
|
||||
if file:
|
||||
file.close()
|
||||
|
@ -1,20 +1,56 @@
|
||||
"""Process Model."""
|
||||
from flask.app import Flask
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
||||
|
||||
def test_initializes_files_as_empty_array() -> None:
|
||||
"""Test_initializes_files_as_empty_array."""
|
||||
process_model_one = create_test_process_model(
|
||||
id="model_one", display_name="Model One"
|
||||
)
|
||||
assert process_model_one.files == []
|
||||
assert process_model_one.libraries == []
|
||||
class TestProcessModel(BaseTest):
|
||||
"""TestProcessModel."""
|
||||
|
||||
def test_initializes_files_as_empty_array(self) -> None:
|
||||
"""Test_initializes_files_as_empty_array."""
|
||||
process_model_one = self.create_test_process_model(
|
||||
id="model_one", display_name="Model One"
|
||||
)
|
||||
assert process_model_one.files == []
|
||||
assert process_model_one.libraries == []
|
||||
|
||||
def create_test_process_model(id: str, display_name: str) -> ProcessModelInfo:
|
||||
"""Create_test_process_model."""
|
||||
return ProcessModelInfo(
|
||||
id=id,
|
||||
display_name=display_name,
|
||||
description=display_name,
|
||||
)
|
||||
def test_can_run_process_model_with_call_activities(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_can_run_process_model_with_call_activities."""
|
||||
process_model = load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
|
||||
bpmn_file_names = [
|
||||
"call_activity_level_2b",
|
||||
"call_activity_level_2",
|
||||
"call_activity_level_3",
|
||||
]
|
||||
for bpmn_file_name in bpmn_file_names:
|
||||
load_test_spec(
|
||||
bpmn_file_name,
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model
|
||||
)
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.do_engine_steps()
|
||||
|
||||
def create_test_process_model(self, id: str, display_name: str) -> ProcessModelInfo:
|
||||
"""Create_test_process_model."""
|
||||
return ProcessModelInfo(
|
||||
id=id,
|
||||
display_name=display_name,
|
||||
description=display_name,
|
||||
)
|
||||
|
@ -1,13 +1,97 @@
|
||||
"""Test_message_service."""
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
|
||||
|
||||
|
||||
class TestSpecFileService(BaseTest):
|
||||
"""TestSpecFileService."""
|
||||
|
||||
def test_can_check_for_messages_in_bpmn_xml(
|
||||
call_activity_nested_relative_file_path = os.path.join(
|
||||
"test_process_group_id", "call_activity_nested", "call_activity_nested.bpmn"
|
||||
)
|
||||
|
||||
def test_can_store_process_ids_for_lookup(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_can_check_for_messages_in_bpmn_xml."""
|
||||
assert True
|
||||
"""Test_can_store_process_ids_for_lookup."""
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
assert bpmn_process_id_lookups[0].bpmn_process_identifier == "Level1"
|
||||
assert (
|
||||
bpmn_process_id_lookups[0].bpmn_file_relative_path
|
||||
== self.call_activity_nested_relative_file_path
|
||||
)
|
||||
|
||||
def test_fails_to_save_duplicate_process_id(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_fails_to_save_duplicate_process_id."""
|
||||
bpmn_process_identifier = "Level1"
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
assert (
|
||||
bpmn_process_id_lookups[0].bpmn_process_identifier
|
||||
== bpmn_process_identifier
|
||||
)
|
||||
assert (
|
||||
bpmn_process_id_lookups[0].bpmn_file_relative_path
|
||||
== self.call_activity_nested_relative_file_path
|
||||
)
|
||||
with pytest.raises(ApiError) as exception:
|
||||
load_test_spec(
|
||||
"call_activity_nested_duplicate",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested_duplicate",
|
||||
)
|
||||
assert f"Process id ({bpmn_process_identifier}) has already been used" in str(
|
||||
exception.value
|
||||
)
|
||||
|
||||
def test_updates_relative_file_path_when_appropriate(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_updates_relative_file_path_when_appropriate."""
|
||||
bpmn_process_identifier = "Level1"
|
||||
bpmn_file_relative_path = os.path.join(
|
||||
"test_process_group_id", "call_activity_nested", "new_bpmn_file.bpmn"
|
||||
)
|
||||
process_id_lookup = BpmnProcessIdLookup(
|
||||
bpmn_process_identifier=bpmn_process_identifier,
|
||||
bpmn_file_relative_path=bpmn_file_relative_path,
|
||||
)
|
||||
db.session.add(process_id_lookup)
|
||||
db.session.commit()
|
||||
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
assert (
|
||||
bpmn_process_id_lookups[0].bpmn_process_identifier
|
||||
== bpmn_process_identifier
|
||||
)
|
||||
assert (
|
||||
bpmn_process_id_lookups[0].bpmn_file_relative_path
|
||||
== self.call_activity_nested_relative_file_path
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user