Skip to content

Commit e16eaf2

Browse files
authored
[FEAT] BpmnElementsRegistry API returns shape incoming/outgoing (#2523)
This will facilitate the implementation of "path-related" use cases. BREAKING CHANGES: the `BpmnSemantic` type includes new properties that are mandatory.
1 parent c74bffc commit e16eaf2

File tree

7 files changed

+68
-27
lines changed

7 files changed

+68
-27
lines changed

src/component/registry/bpmn-model-registry.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type BpmnModel from '../../model/bpmn/internal/BpmnModel';
1818
import type Shape from '../../model/bpmn/internal/shape/Shape';
1919
import type { Edge } from '../../model/bpmn/internal/edge/edge';
2020
import { Flow } from '../../model/bpmn/internal/edge/flows';
21-
import type { BpmnSemantic, EdgeBpmnSemantic } from './types';
21+
import type { BaseBpmnSemantic, BpmnSemantic, EdgeBpmnSemantic, ShapeBpmnSemantic } from './types';
2222
import { ShapeBpmnMarkerKind, ShapeUtil } from '../../model/bpmn/internal';
2323
import type { ShapeBpmnSubProcess } from '../../model/bpmn/internal/shape/ShapeBpmnElement';
2424
import ShapeBpmnElement from '../../model/bpmn/internal/shape/ShapeBpmnElement';
@@ -44,19 +44,22 @@ export class BpmnModelRegistry {
4444
this.onLoadCallback = callback;
4545
}
4646

47-
getBpmnSemantic(bpmnElementId: string): BpmnSemantic | EdgeBpmnSemantic | undefined {
47+
getBpmnSemantic(bpmnElementId: string): BpmnSemantic | undefined {
4848
const element = this.searchableModel.elementById(bpmnElementId);
4949
if (!element) {
5050
return undefined;
5151
}
5252
const bpmnElement = element.bpmnElement;
5353
const isShape = bpmnElement instanceof ShapeBpmnElement;
54-
const semantic: BpmnSemantic = { id: bpmnElementId, name: bpmnElement.name, isShape: isShape, kind: bpmnElement.kind };
54+
const semantic: BaseBpmnSemantic = { id: bpmnElementId, name: bpmnElement.name, isShape: isShape, kind: bpmnElement.kind };
5555
if (bpmnElement instanceof Flow) {
5656
(<EdgeBpmnSemantic>semantic).sourceRefId = bpmnElement.sourceRefId;
5757
(<EdgeBpmnSemantic>semantic).targetRefId = bpmnElement.targetRefId;
58+
} else {
59+
(<ShapeBpmnSemantic>semantic).incomingIds = bpmnElement.incomingIds;
60+
(<ShapeBpmnSemantic>semantic).outgoingIds = bpmnElement.outgoingIds;
5861
}
59-
return semantic;
62+
return <BpmnSemantic>semantic;
6063
}
6164
}
6265

src/component/registry/types.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type { BpmnElementKind } from '../../model/bpmn/internal';
1919
/**
2020
* @category Custom Behavior
2121
*/
22-
export interface BpmnSemantic {
22+
export interface BaseBpmnSemantic {
2323
id: string;
2424
name: string;
2525
/** `true` when relates to a BPMN Shape, `false` when relates to a BPMN Edge. */
@@ -28,13 +28,28 @@ export interface BpmnSemantic {
2828
}
2929

3030
/**
31-
* Extended properties available when {@link BpmnSemantic.isShape} is `false`.
31+
* Extended properties available when {@link BaseBpmnSemantic.isShape} is `false`.
32+
* @category Custom Behavior
3233
*/
33-
export interface EdgeBpmnSemantic extends BpmnSemantic {
34+
export interface EdgeBpmnSemantic extends BaseBpmnSemantic {
3435
sourceRefId: string;
3536
targetRefId: string;
3637
}
3738

39+
/**
40+
* Extended properties available when {@link BaseBpmnSemantic.isShape} is `true`.
41+
* @category Custom Behavior
42+
*/
43+
export interface ShapeBpmnSemantic extends BaseBpmnSemantic {
44+
incomingIds: string[];
45+
outgoingIds: string[];
46+
}
47+
48+
/**
49+
* @category Custom Behavior
50+
*/
51+
export type BpmnSemantic = EdgeBpmnSemantic | ShapeBpmnSemantic;
52+
3853
/**
3954
* @category Custom Behavior
4055
*/

test/integration/dom.bpmn.elements.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('Bpmn Elements registry - retrieve BPMN elements', () => {
4848
const bpmnElements = bpmnVisualization.bpmnElementsRegistry.getElementsByIds(['StartEvent_1', 'Flow_2']);
4949
expect(bpmnElements).toHaveLength(2);
5050

51-
expectStartEventBpmnElement(bpmnElements[0], { id: 'StartEvent_1', name: 'Start Event 1' });
51+
expectStartEventBpmnElement(bpmnElements[0], { id: 'StartEvent_1', name: 'Start Event 1', outgoing: ['Flow_1'] });
5252
expectSequenceFlowBpmnElement(bpmnElements[1], { id: 'Flow_2', source: 'Activity_1', target: 'EndEvent_1' });
5353
});
5454

@@ -71,7 +71,7 @@ describe('Bpmn Elements registry - retrieve BPMN elements', () => {
7171
const bpmnElements = bpmnVisualization.bpmnElementsRegistry.getElementsByKinds(ShapeBpmnElementKind.TASK);
7272
expect(bpmnElements).toHaveLength(1);
7373

74-
expectTaskBpmnElement(bpmnElements[0], { id: 'Activity_1', name: 'Task 1' });
74+
expectTaskBpmnElement(bpmnElements[0], { id: 'Activity_1', name: 'Task 1', incoming: ['Flow_1'], outgoing: ['Flow_2'] });
7575
});
7676

7777
it('Pass a single kind related to several existing elements', async () => {

test/integration/helpers/semantic-with-svg-utils.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import type { BpmnElement, EdgeBpmnSemantic } from '../../../src/component/registry';
17-
import type { ExpectedBaseBpmnElement, ExpectedFlowElement } from '../../unit/helpers/bpmn-semantic-utils';
16+
import type { BpmnElement, EdgeBpmnSemantic, ShapeBpmnSemantic } from '../../../src/component/registry';
17+
import type { ExpectedBaseBpmnElement, ExpectedFlowElement, ExpectedFlowNodeElement } from '../../unit/helpers/bpmn-semantic-utils';
1818
import { expectEndEvent, expectPool, expectSequenceFlow, expectServiceTask, expectStartEvent, expectTask } from '../../unit/helpers/bpmn-semantic-utils';
1919
import { expectSvgEvent, expectSvgPool, expectSvgSequenceFlow, expectSvgTask } from './html-utils';
2020

21-
export function expectStartEventBpmnElement(bpmnElement: BpmnElement, expected: ExpectedBaseBpmnElement): void {
22-
expectStartEvent(bpmnElement.bpmnSemantic, expected);
21+
export function expectStartEventBpmnElement(bpmnElement: BpmnElement, expected: ExpectedFlowNodeElement): void {
22+
expectStartEvent(<ShapeBpmnSemantic>bpmnElement.bpmnSemantic, expected);
2323
expectSvgEvent(bpmnElement.htmlElement);
2424
}
2525

@@ -33,8 +33,8 @@ export function expectSequenceFlowBpmnElement(bpmnElement: BpmnElement, expected
3333
expectSvgSequenceFlow(bpmnElement.htmlElement);
3434
}
3535

36-
export function expectTaskBpmnElement(bpmnElement: BpmnElement, expected: ExpectedBaseBpmnElement): void {
37-
expectTask(bpmnElement.bpmnSemantic, expected);
36+
export function expectTaskBpmnElement(bpmnElement: BpmnElement, expected: ExpectedFlowNodeElement): void {
37+
expectTask(<ShapeBpmnSemantic>bpmnElement.bpmnSemantic, expected);
3838
expectSvgTask(bpmnElement.htmlElement);
3939
}
4040

test/unit/component/registry/bpmn-model-registry.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import type { EdgeBpmnSemantic } from '../../../../src/component/registry';
17+
import type { EdgeBpmnSemantic, ShapeBpmnSemantic } from '../../../../src/component/registry';
1818
import { BpmnModelRegistry } from '../../../../src/component/registry/bpmn-model-registry';
1919
import { expectAssociationFlow, expectLane, expectMessageFlow, expectPool, expectSequenceFlow, expectStartEvent } from '../../helpers/bpmn-semantic-utils';
2020
import { associationFlowInModel, laneInModel, messageFlowInModel, poolInModel, sequenceFlowInModel, startEventInModel } from '../../helpers/bpmn-model-utils';
@@ -47,9 +47,9 @@ describe('Bpmn Model registry', () => {
4747
});
4848

4949
it('search flowNode', () => {
50-
bpmnModelRegistry.load(startEventInModel('start event id', 'start event name'));
51-
const bpmnSemantic = bpmnModelRegistry.getBpmnSemantic('start event id');
52-
expectStartEvent(bpmnSemantic, { id: 'start event id', name: 'start event name' });
50+
bpmnModelRegistry.load(startEventInModel('start event id', 'start event name', { incomingIds: ['incoming_1'], outgoingIds: ['outgoing_1', 'outgoing_2'] }));
51+
const bpmnSemantic = <ShapeBpmnSemantic>bpmnModelRegistry.getBpmnSemantic('start event id');
52+
expectStartEvent(bpmnSemantic, { id: 'start event id', name: 'start event name', incoming: ['incoming_1'], outgoing: ['outgoing_1', 'outgoing_2'] });
5353
});
5454

5555
it('search lane', () => {

test/unit/helpers/bpmn-model-utils.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ export const associationFlowInModel = (id: string, name: string, source: string,
6666
return flowInModel(newAssociationFlow, id, name, source, target);
6767
};
6868

69-
export const startEventInModel = (id: string, name: string): BpmnModel => {
69+
export const startEventInModel = (id: string, name: string, extras?: ShapeBpmnElementExtraProperties): BpmnModel => {
7070
const bpmnModel = newBpmnModel();
71-
bpmnModel.flowNodes.push(newStartEvent('parentId', id, name));
71+
bpmnModel.flowNodes.push(newStartEvent('parentId', id, name, extras));
7272
return bpmnModel;
7373
};
7474

@@ -84,8 +84,20 @@ export const poolInModel = (id: string, name: string): BpmnModel => {
8484
return bpmnModel;
8585
};
8686

87-
const newStartEvent = (parent: string, id: string, name: string): Shape =>
88-
new Shape(buildShapeId(id), new ShapeBpmnStartEvent(id, name, ShapeBpmnEventDefinitionKind.TIMER, parent));
87+
const withExtras = (bpmnElement: ShapeBpmnElement, extras?: ShapeBpmnElementExtraProperties): ShapeBpmnElement => {
88+
bpmnElement.incomingIds = extras?.incomingIds ?? [];
89+
bpmnElement.outgoingIds = extras?.outgoingIds ?? [];
90+
return bpmnElement;
91+
};
92+
93+
export type ShapeBpmnElementExtraProperties = {
94+
incomingIds?: string[];
95+
outgoingIds?: string[];
96+
};
97+
98+
const newStartEvent = (parent: string, id: string, name: string, extras?: ShapeBpmnElementExtraProperties): Shape => {
99+
return new Shape(buildShapeId(id), withExtras(new ShapeBpmnStartEvent(id, name, ShapeBpmnEventDefinitionKind.TIMER, parent), extras));
100+
};
89101
const newBoundaryEvent = (parent: string, id: string, name: string): Shape =>
90102
new Shape(buildShapeId(id), new ShapeBpmnBoundaryEvent(id, name, ShapeBpmnEventDefinitionKind.CANCEL, parent));
91103

test/unit/helpers/bpmn-semantic-utils.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import type { BpmnSemantic, EdgeBpmnSemantic } from '../../../src/component/registry';
17+
import type { BpmnSemantic, EdgeBpmnSemantic, ShapeBpmnSemantic } from '../../../src/component/registry';
1818
import { FlowKind, ShapeBpmnElementKind } from '../../../src/model/bpmn/internal';
1919

2020
export interface ExpectedBaseBpmnElement {
@@ -27,6 +27,11 @@ export interface ExpectedFlowElement extends ExpectedBaseBpmnElement {
2727
target: string;
2828
}
2929

30+
export interface ExpectedFlowNodeElement extends ExpectedBaseBpmnElement {
31+
incoming?: string[];
32+
outgoing?: string[];
33+
}
34+
3035
const expectFlow = (bpmnSemantic: EdgeBpmnSemantic, expected: ExpectedFlowElement): void => {
3136
expect(bpmnSemantic.id).toEqual(expected.id);
3237
expect(bpmnSemantic.name).toEqual(expected.name);
@@ -56,9 +61,15 @@ function expectShape(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpmnEleme
5661
expect(bpmnSemantic.isShape).toBeTruthy();
5762
}
5863

59-
export function expectStartEvent(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpmnElement): void {
64+
function expectedFlowNode(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedFlowNodeElement): void {
6065
expectShape(bpmnSemantic, expected);
66+
expect(bpmnSemantic.incomingIds).toEqual(expected.incoming ?? []);
67+
expect(bpmnSemantic.outgoingIds).toEqual(expected.outgoing ?? []);
68+
}
69+
70+
export function expectStartEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedFlowNodeElement): void {
6171
expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.EVENT_START);
72+
expectedFlowNode(bpmnSemantic, expected);
6273
}
6374

6475
export function expectEndEvent(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpmnElement): void {
@@ -76,9 +87,9 @@ export function expectPool(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpm
7687
expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.POOL);
7788
}
7889

79-
export function expectTask(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpmnElement): void {
80-
expectShape(bpmnSemantic, expected);
90+
export function expectTask(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedFlowNodeElement): void {
8191
expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.TASK);
92+
expectedFlowNode(bpmnSemantic, expected);
8293
}
8394

8495
export function expectServiceTask(bpmnSemantic: BpmnSemantic, expected: ExpectedBaseBpmnElement): void {

0 commit comments

Comments
 (0)