Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] detect activities and gateways in subprocess #514

Merged
merged 6 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/component/parser/json/converter/ProcessConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ export default class ProcessConverter {
}

private buildShapeBpmnSubProcess(bpmnElement: TSubProcess, processId: string, markers: ShapeBpmnMarkerKind[]): ShapeBpmnSubProcess {
this.buildSubProcessInnerElements(bpmnElement);
if (!bpmnElement.triggeredByEvent) {
this.buildSubProcessInnerElements(bpmnElement);
return new ShapeBpmnSubProcess(bpmnElement.id, bpmnElement.name, ShapeBpmnSubProcessKind.EMBEDDED, processId, markers);
}
return new ShapeBpmnSubProcess(bpmnElement.id, bpmnElement.name, ShapeBpmnSubProcessKind.EVENT, processId, markers);
Expand All @@ -250,7 +250,7 @@ export default class ProcessConverter {
const process = subProcess;

// flow nodes
ShapeUtil.topLevelBpmnEventKinds()
ShapeUtil.flowNodeKinds()
.filter(kind => kind != ShapeBpmnElementKind.EVENT_BOUNDARY)
.forEach(kind => this.buildFlowNodeBpmnElements(processId, process[kind], kind));
// process boundary events afterwards as we need its parent activity to be available when building it
Expand Down
2 changes: 1 addition & 1 deletion src/model/bpmn/shape/ShapeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default class ShapeUtil {

public static flowNodeKinds(): ShapeBpmnElementKind[] {
return Object.values(ShapeBpmnElementKind).filter(kind => {
return kind != ShapeBpmnElementKind.LANE;
return !ShapeUtil.isPoolOrLane(kind);
});
}

Expand Down
208 changes: 123 additions & 85 deletions test/unit/component/parser/json/BpmnJsonParser.sub.process.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ import { ShapeBpmnEventKind } from '../../../../../src/model/bpmn/shape/ShapeBpm
import BpmnModel from '../../../../../src/model/bpmn/BpmnModel';
import { getEventShapes } from './BpmnJsonParser.event.test';

function toEventDefinition(eventKind: ShapeBpmnEventKind): string {
return `${eventKind}EventDefinition`;
}

function expectNoEdgePoolLane(model: BpmnModel): void {
expect(model.lanes).toHaveLength(0);
expect(model.pools).toHaveLength(0);
expect(model.edges).toHaveLength(0);
}

describe('parse bpmn as json for sub-process', () => {
each([
['embedded', false, ShapeBpmnSubProcessKind.EMBEDDED],
Expand Down Expand Up @@ -189,98 +199,126 @@ describe('parse bpmn as json for sub-process', () => {
bpmnElementMarkers: [ShapeBpmnMarkerKind.EXPAND],
});
});
}

function toEventDefinition(eventKind: ShapeBpmnEventKind): string {
return `${eventKind}EventDefinition`;
}

function expectNoEdgePoolLane(model: BpmnModel): void {
expect(model.lanes).toHaveLength(0);
expect(model.pools).toHaveLength(0);
expect(model.edges).toHaveLength(0);
}

it(`should convert event elements in sub-process`, () => {
const json = {
definitions: {
targetNamespace: '',
process: {
subProcess: {
id: 'sub-process_id_1',
collapsed: false,
startEvent: {
id: 'sub-process_id_1_startEvent_1',
name: 'SubProcess Start Event',
eventDefinition: toEventDefinition(ShapeBpmnEventKind.TIMER),
},
endEvent: {
id: 'sub-process_id_1_endEvent_1',
name: 'SubProcess End Event',
eventDefinition: toEventDefinition(ShapeBpmnEventKind.TERMINATE),
},
it(`should convert activities, events and gateways in sub-process`, () => {
const json = {
definitions: {
targetNamespace: '',
process: {
subProcess: {
id: 'sub-process_id_1',
collapsed: false,
triggeredByEvent: triggeredByEvent,
startEvent: {
id: 'sub-process_id_1_startEvent_1',
name: 'SubProcess Start Event',
eventDefinition: toEventDefinition(ShapeBpmnEventKind.TIMER),
},
},
BPMNDiagram: {
name: 'process 0',
BPMNPlane: {
BPMNShape: [
{
id: 'shape_sub-process_id_1',
bpmnElement: 'sub-process_id_1',
Bounds: { x: 365, y: 235, width: 300, height: 200 },
isExpanded: true,
},
{
id: 'shape_sub-process_id_1_startEvent_1',
bpmnElement: 'sub-process_id_1_startEvent_1',
Bounds: { x: 465, y: 335, width: 10, height: 10 },
},
{
id: 'shape_sub-process_id_1_endEvent_1',
bpmnElement: 'sub-process_id_1_endEvent_1',
Bounds: { x: 565, y: 335, width: 20, height: 20 },
},
],
endEvent: {
id: 'sub-process_id_1_endEvent_1',
name: 'SubProcess End Event',
eventDefinition: toEventDefinition(ShapeBpmnEventKind.TERMINATE),
},
userTask: {
id: 'sub-process_id_1_userTask_1',
name: 'SubProcess User Task',
},
exclusiveGateway: {
id: 'sub-process_id_1_exclusiveGateway_1',
name: 'SubProcess Exclusive Gateway',
},
},
},
};
BPMNDiagram: {
name: 'process 0',
BPMNPlane: {
BPMNShape: [
{
id: 'shape_sub-process_id_1',
bpmnElement: 'sub-process_id_1',
Bounds: { x: 365, y: 235, width: 300, height: 200 },
isExpanded: true,
},
{
id: 'shape_sub-process_id_1_startEvent_1',
bpmnElement: 'sub-process_id_1_startEvent_1',
Bounds: { x: 465, y: 335, width: 10, height: 10 },
},
{
id: 'shape_sub-process_id_1_userTask_1',
bpmnElement: 'sub-process_id_1_userTask_1',
Bounds: { x: 465, y: 335, width: 10, height: 10 },
},
{
id: 'shape_sub-process_id_1_exclusiveGateway_1',
bpmnElement: 'sub-process_id_1_exclusiveGateway_1',
Bounds: { x: 565, y: 335, width: 20, height: 20 },
},
{
id: 'shape_sub-process_id_1_endEvent_1',
bpmnElement: 'sub-process_id_1_endEvent_1',
Bounds: { x: 565, y: 335, width: 20, height: 20 },
},
],
},
},
},
};

const model = parseJson(json);
expectNoEdgePoolLane(model);
const model = parseJson(json);
expectNoEdgePoolLane(model);

verifySubProcess(model, expectedShapeBpmnSubProcessKind, 1);
verifyShape(model.flowNodes[0], {
shapeId: 'shape_sub-process_id_1',
bpmnElementId: 'sub-process_id_1',
bpmnElementName: undefined,
bpmnElementKind: ShapeBpmnElementKind.SUB_PROCESS,
bounds: {
x: 365,
y: 235,
width: 300,
height: 200,
},
});
const eventShapes = getEventShapes(model);
expect(eventShapes).toHaveLength(2);
verifyShape(eventShapes[0], {
shapeId: 'shape_sub-process_id_1_startEvent_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_startEvent_1',
bpmnElementName: 'SubProcess Start Event',
bpmnElementKind: ShapeBpmnElementKind.EVENT_START,
bounds: { x: 465, y: 335, width: 10, height: 10 },
});
verifyShape(eventShapes[1], {
shapeId: 'shape_sub-process_id_1_endEvent_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_endEvent_1',
bpmnElementName: 'SubProcess End Event',
bpmnElementKind: ShapeBpmnElementKind.EVENT_END,
bounds: { x: 565, y: 335, width: 20, height: 20 },
});
verifySubProcess(model, expectedShapeBpmnSubProcessKind, 1);
verifyShape(model.flowNodes[0], {
shapeId: 'shape_sub-process_id_1',
bpmnElementId: 'sub-process_id_1',
bpmnElementName: undefined,
bpmnElementKind: ShapeBpmnElementKind.SUB_PROCESS,
bounds: {
x: 365,
y: 235,
width: 300,
height: 200,
},
});
}

const eventShapes = getEventShapes(model);
expect(eventShapes).toHaveLength(2);
verifyShape(eventShapes[0], {
shapeId: 'shape_sub-process_id_1_startEvent_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_startEvent_1',
bpmnElementName: 'SubProcess Start Event',
bpmnElementKind: ShapeBpmnElementKind.EVENT_START,
bounds: { x: 465, y: 335, width: 10, height: 10 },
});
verifyShape(eventShapes[1], {
shapeId: 'shape_sub-process_id_1_endEvent_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_endEvent_1',
bpmnElementName: 'SubProcess End Event',
bpmnElementKind: ShapeBpmnElementKind.EVENT_END,
bounds: { x: 565, y: 335, width: 20, height: 20 },
});

verifyShape(model.flowNodes[2], {
shapeId: 'shape_sub-process_id_1_userTask_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_userTask_1',
bpmnElementName: 'SubProcess User Task',
bpmnElementKind: ShapeBpmnElementKind.TASK_USER,
bounds: { x: 465, y: 335, width: 10, height: 10 },
});

verifyShape(model.flowNodes[3], {
shapeId: 'shape_sub-process_id_1_exclusiveGateway_1',
parentId: 'sub-process_id_1',
bpmnElementId: 'sub-process_id_1_exclusiveGateway_1',
bpmnElementName: 'SubProcess Exclusive Gateway',
bpmnElementKind: ShapeBpmnElementKind.GATEWAY_EXCLUSIVE,
bounds: { x: 565, y: 335, width: 20, height: 20 },
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { readFileSync } from '../../../../helpers/file-helper';
import { TSubProcess } from '../../../../../src/component/parser/xml/bpmn-json-model/baseElement/flowNode/activity/activity';
import { ensureIsArray } from '../../../../../src/component/parser/json/converter/ConverterUtil';
import { TStartEvent } from '../../../../../src/component/parser/xml/bpmn-json-model/baseElement/flowNode/event';
import { TTask } from '../../../../../src/component/parser/xml/bpmn-json-model/baseElement/flowNode/activity/task';

describe('parse bpmn as xml for Trisotech BPMN Modeler 6.2.0', () => {
it('bpmn with process with extension, ensure elements are present', () => {
Expand All @@ -32,12 +33,16 @@ describe('parse bpmn as xml for Trisotech BPMN Modeler 6.2.0', () => {
},
});

const process: TProcess = json.definitions.process as TProcess[];
const process = json.definitions.process as TProcess[];
expect(process).toHaveLength(2);
const subProcess1 = process[0] as TSubProcess;
expect(subProcess1.task).toHaveLength(2);
const subProcess1StartEvents: TStartEvent[] = ensureIsArray(subProcess1.startEvent);
expect(subProcess1StartEvents).toHaveLength(1);
expect(subProcess1StartEvents[0].name).toBe('Start Event 2');

const subProcess1Tasks: TTask[] = ensureIsArray(subProcess1.task);
expect(subProcess1Tasks).toHaveLength(2);
expect(subProcess1Tasks[0].name).toBe('Task 3');
expect(subProcess1Tasks[1].name).toBe('Task 5');
});
});