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

[BUG] Fix some types of BPMN Json model #444

Merged
merged 2 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
27 changes: 18 additions & 9 deletions src/component/parser/json/converter/AbstractConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,25 @@
import { JsonConverter, JsonCustomConvert } from 'json2typescript';
import JsonConvertConfig from './JsonConvertConfig';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function ensureIsArray(elements: Array<any> | any, acceptEmptyString = false): Array<any> {
if (elements === undefined || elements === null || (!acceptEmptyString && elements === '')) {
elements = [];
} else if (elements === '' && acceptEmptyString) {
return [{}];
} else if (!Array.isArray(elements)) {
elements = [elements];
function convertEmptyStringAndObject<T>(element: string | T, acceptEmptyString: boolean): T {
if (element === '') {
return acceptEmptyString ? ({} as T) : undefined;
}
return elements;
return element as T;
}

export function ensureIsArray<T>(elements: (T | string)[] | T | string, acceptEmptyString = false): Array<T> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ is the introduction of generics also done to cover #421 (remove usage of any)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see that. I introduce that to be sure what we manipulate after calling this method, in order to use the BPMN Json interfaces :)

if (elements === undefined || elements === null) {
return [];
}

let returnedArray;
if (!Array.isArray(elements)) {
returnedArray = [convertEmptyStringAndObject(elements, acceptEmptyString)];
} else {
returnedArray = elements.map(element => convertEmptyStringAndObject(element, acceptEmptyString));
}
return returnedArray.filter(value => value);
}

@JsonConverter
Expand Down
10 changes: 7 additions & 3 deletions src/component/parser/json/converter/CollaborationConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,13 @@ export function findMessageFlow(id: string): MessageFlow {

@JsonConverter
export default class CollaborationConverter extends AbstractConverter<Collaboration> {
deserialize(collaboration: TCollaboration): Collaboration {
deserialize(collaborations: string | TCollaboration | (string | TCollaboration)[]): Collaboration {
try {
// Deletes everything in the array, which does hit other references. For better performance.
convertedProcessRefParticipants.length = 0;
convertedMessageFlows.length = 0;

this.buildParticipant(collaboration['participant']);
this.buildMessageFlows(collaboration[FlowKind.MESSAGE_FLOW]);
ensureIsArray(collaborations).forEach(collaboration => this.parseCollaboratation(collaboration));

return {};
} catch (e) {
Expand All @@ -56,6 +55,11 @@ export default class CollaborationConverter extends AbstractConverter<Collaborat
}
}

private parseCollaboratation(collaboration: TCollaboration): void {
this.buildParticipant(collaboration['participant']);
this.buildMessageFlows(collaboration[FlowKind.MESSAGE_FLOW]);
}

private buildParticipant(bpmnElements: Array<TParticipant> | TParticipant): void {
ensureIsArray(bpmnElements).forEach(participant => {
if (participant.processRef) {
Expand Down
12 changes: 7 additions & 5 deletions src/component/parser/json/converter/DiagramConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@ export default class DiagramConverter extends AbstractConverter<BpmnModel> {
this.convertedFonts = new Map();

ensureIsArray(bpmnLabelStyle).forEach(labelStyle => {
const font = labelStyle.Font;
if (font) {
ensureIsArray(labelStyle.Font).forEach(font => {
this.convertedFonts.set(labelStyle.id, new Font(font.name, font.size, font.isBold, font.isItalic, font.isUnderline, font.isStrikeThrough));
}
});
});
}

Expand Down Expand Up @@ -139,12 +138,15 @@ export default class DiagramConverter extends AbstractConverter<BpmnModel> {
}
}

private deserializeEdges(edges: BPMNEdge): Edge[] {
private deserializeEdges(edges: BPMNEdge | BPMNEdge[]): Edge[] {
return ensureIsArray(edges).map(edge => {
const flow = findSequenceFlow(edge.bpmnElement) || findMessageFlow(edge.bpmnElement) || findAssociationFlow(edge.bpmnElement);
const waypoints = this.deserializeWaypoints(edge.waypoint);
const label = this.deserializeLabel(edge.BPMNLabel, edge.id);
const messageVisibleKind = edge.messageVisibleKind ? edge.messageVisibleKind : MessageVisibleKind.NONE;

// TODO Remove messageVisibleKind conversion type when we merge/simplify internal model with BPMN json model
const messageVisibleKind = edge.messageVisibleKind ? ((edge.messageVisibleKind as unknown) as MessageVisibleKind) : MessageVisibleKind.NONE;

return new Edge(edge.id, flow, waypoints, label, messageVisibleKind);
});
}
Expand Down
9 changes: 6 additions & 3 deletions src/component/parser/json/converter/ProcessConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { TSubProcess } from '../../xml/bpmn-json-model/baseElement/flowNode/acti
import { TLane, TLaneSet } from '../../xml/bpmn-json-model/baseElement/baseElement';
import { TSequenceFlow } from '../../xml/bpmn-json-model/baseElement/flowElement';
import { TAssociation } from '../../xml/bpmn-json-model/baseElement/artifact';
import { AssociationDirectionKind } from '../../../../model/bpmn/edge/AssociationDirectionKind';

const convertedFlowNodeBpmnElements: ShapeBpmnElement[] = [];
const convertedLaneBpmnElements: ShapeBpmnElement[] = [];
Expand Down Expand Up @@ -70,7 +71,7 @@ interface EventDefinition {
@JsonConverter
export default class ProcessConverter extends AbstractConverter<Process> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
deserialize(processes: Array<TProcess> | TProcess): Process {
deserialize(processes: string | TProcess | (string | TProcess)[]): Process {
try {
// Deletes everything in the array, which does hit other references. For better performance.
convertedFlowNodeBpmnElements.length = 0;
Expand Down Expand Up @@ -190,7 +191,7 @@ export default class ProcessConverter extends AbstractConverter<Process> {
}

private assignParentOfLaneFlowNodes(lane: TLane): void {
ensureIsArray(lane.flowNodeRef).forEach(flowNodeRef => {
ensureIsArray<string>(lane.flowNodeRef).forEach(flowNodeRef => {
const shapeBpmnElement = findFlowNodeBpmnElement(flowNodeRef);
const laneId = lane.id;
if (shapeBpmnElement) {
Expand All @@ -214,7 +215,9 @@ export default class ProcessConverter extends AbstractConverter<Process> {

private buildAssociationFlows(bpmnElements: Array<TAssociation> | TAssociation): void {
ensureIsArray(bpmnElements).forEach(association => {
const convertedAssociationFlow = new AssociationFlow(association.id, association.name, association.sourceRef, association.targetRef, association.associationDirection);
// TODO Remove associationDirection conversion type when we merge/simplify internal model with BPMN json model
const direction = (association.associationDirection as unknown) as AssociationDirectionKind;
const convertedAssociationFlow = new AssociationFlow(association.id, undefined, association.sourceRef, association.targetRef, direction);
convertedAssociationFlows.push(convertedAssociationFlow);
});
}
Expand Down
26 changes: 13 additions & 13 deletions src/component/parser/xml/bpmn-json-model/BPMN20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface TDefinitions {
// rootElement
category?: TCategory | TCategory[];
choreography?: TChoreography | TChoreography[];
collaboration?: TCollaboration | TCollaboration[];
collaboration?: string | TCollaboration | (string | TCollaboration)[];
correlationProperty?: TCorrelationProperty | TCorrelationProperty[];
dataStore?: TDataStore | TDataStore[];
endPoint?: TEndPoint | TEndPoint[];
Expand All @@ -79,23 +79,23 @@ export interface TDefinitions {
message?: TMessage | TMessage[];
partnerEntity?: TPartnerEntity | TPartnerEntity[];
partnerRole?: TPartnerRole | TPartnerRole[];
process?: string | TProcess | TProcess[];
process?: string | TProcess | (string | TProcess)[];
resource?: TResource | TResource[];
rootElement?: TRootElement | TRootElement[];
signal?: TSignal | TSignal[];

// eventDefinition
eventDefinition?: string | TEventDefinition | TEventDefinition[];
cancelEventDefinition?: string | TCancelEventDefinition | TCancelEventDefinition[];
compensateEventDefinition?: string | TCompensateEventDefinition | TCompensateEventDefinition[];
conditionalEventDefinition?: string | TConditionalEventDefinition | TConditionalEventDefinition[];
errorEventDefinition?: string | TErrorEventDefinition | TErrorEventDefinition[];
escalationEventDefinition?: string | TEscalationEventDefinition | TEscalationEventDefinition[];
linkEventDefinition?: string | TLinkEventDefinition | TLinkEventDefinition[];
messageEventDefinition?: string | TMessageEventDefinition | TMessageEventDefinition[];
signalEventDefinition?: string | TSignalEventDefinition | TSignalEventDefinition[];
terminateEventDefinition?: string | TTerminateEventDefinition | TTerminateEventDefinition[];
timerEventDefinition?: string | TTimerEventDefinition | TTimerEventDefinition[];
eventDefinition?: string | TEventDefinition | (string | TEventDefinition)[];
cancelEventDefinition?: string | TCancelEventDefinition | (string | TCancelEventDefinition)[];
compensateEventDefinition?: string | TCompensateEventDefinition | (string | TCompensateEventDefinition)[];
conditionalEventDefinition?: string | TConditionalEventDefinition | (string | TConditionalEventDefinition)[];
errorEventDefinition?: string | TErrorEventDefinition | (string | TErrorEventDefinition)[];
escalationEventDefinition?: string | TEscalationEventDefinition | (string | TEscalationEventDefinition)[];
linkEventDefinition?: string | TLinkEventDefinition | (string | TLinkEventDefinition)[];
messageEventDefinition?: string | TMessageEventDefinition | (string | TMessageEventDefinition)[];
signalEventDefinition?: string | TSignalEventDefinition | (string | TSignalEventDefinition)[];
terminateEventDefinition?: string | TTerminateEventDefinition | (string | TTerminateEventDefinition)[];
timerEventDefinition?: string | TTimerEventDefinition | (string | TTimerEventDefinition)[];

BPMNDiagram?: BPMNDiagram | BPMNDiagram[];
relationship?: TRelationship | TRelationship[];
Expand Down
2 changes: 1 addition & 1 deletion src/component/parser/xml/bpmn-json-model/BPMNDI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export interface BPMNLabel extends Label {
}

export interface BPMNLabelStyle extends Style {
Font?: string | Font | Font[];
Font?: string | Font | (string | Font)[];
}

export enum ParticipantBandKind {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ export interface TCatchEvent extends TEvent {

eventDefinitionRef?: string | string[];
parallelMultiple?: boolean; // default="false"

// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}

export type TIntermediateCatchEvent = TCatchEvent;
Expand All @@ -84,35 +81,23 @@ export interface TThrowEvent extends TEvent {
inputSet?: TInputSet;

// eventDefinition
eventDefinition?: string | TEventDefinition | TEventDefinition[];
cancelEventDefinition?: string | TCancelEventDefinition | TCancelEventDefinition[];
compensateEventDefinition?: string | TCompensateEventDefinition | TCompensateEventDefinition[];
conditionalEventDefinition?: string | TConditionalEventDefinition | TConditionalEventDefinition[];
errorEventDefinition?: string | TErrorEventDefinition | TErrorEventDefinition[];
escalationEventDefinition?: string | TEscalationEventDefinition | TEscalationEventDefinition[];
linkEventDefinition?: string | TLinkEventDefinition | TLinkEventDefinition[];
messageEventDefinition?: string | TMessageEventDefinition | TMessageEventDefinition[];
signalEventDefinition?: string | TSignalEventDefinition | TSignalEventDefinition[];
terminateEventDefinition?: string | TTerminateEventDefinition | TTerminateEventDefinition[];
timerEventDefinition?: string | TTimerEventDefinition | TTimerEventDefinition[];
eventDefinition?: string | TEventDefinition | (string | TEventDefinition)[];
cancelEventDefinition?: string | TCancelEventDefinition | (string | TCancelEventDefinition)[];
compensateEventDefinition?: string | TCompensateEventDefinition | (string | TCompensateEventDefinition)[];
conditionalEventDefinition?: string | TConditionalEventDefinition | (string | TConditionalEventDefinition)[];
errorEventDefinition?: string | TErrorEventDefinition | (string | TErrorEventDefinition)[];
escalationEventDefinition?: string | TEscalationEventDefinition | (string | TEscalationEventDefinition)[];
linkEventDefinition?: string | TLinkEventDefinition | (string | TLinkEventDefinition)[];
messageEventDefinition?: string | TMessageEventDefinition | (string | TMessageEventDefinition)[];
signalEventDefinition?: string | TSignalEventDefinition | (string | TSignalEventDefinition)[];
terminateEventDefinition?: string | TTerminateEventDefinition | (string | TTerminateEventDefinition)[];
timerEventDefinition?: string | TTimerEventDefinition | (string | TTimerEventDefinition)[];

eventDefinitionRef?: string | string[];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}

export interface TImplicitThrowEvent extends TThrowEvent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
export type TImplicitThrowEvent = TThrowEvent;

export interface TIntermediateThrowEvent extends TThrowEvent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
export type TIntermediateThrowEvent = TThrowEvent;

export interface TEndEvent extends TThrowEvent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
export type TEndEvent = TThrowEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ describe('parse bpmn as json for association', () => {
const processJsonAsObjectWithAssociationJsonAsObject = {
association: {
id: 'association_id_0',
name: 'association name',
sourceRef: 'Activity_01',
targetRef: 'Annotation_01',
},
Expand Down Expand Up @@ -53,22 +52,20 @@ describe('parse bpmn as json for association', () => {
verifyEdge(model.edges[0], {
edgeId: 'edge_association_id_0',
bpmnElementId: 'association_id_0',
bpmnElementName: `association name`,
bpmnElementSourceRefId: 'Activity_01',
bpmnElementTargetRefId: 'Annotation_01',
waypoints: [new Waypoint(362, 232)],
});
});

it(`should convert as Edge, when an association (with/without name) is an attribute (as array) of 'process'`, () => {
it(`should convert as Edge, when an association is an attribute (as array) of 'process'`, () => {
const json = {
definitions: {
targetNamespace: '',
process: {
association: [
{
id: 'association_id_0',
name: 'association name',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ why removing the name? is something that does not exist in the BPMN spec?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in the BPMN specification/XDS, there is no name in the association 😉

sourceRef: 'Activity_01',
targetRef: 'Annotation_01',
},
Expand Down Expand Up @@ -105,7 +102,6 @@ describe('parse bpmn as json for association', () => {
verifyEdge(model.edges[0], {
edgeId: 'edge_association_id_0',
bpmnElementId: 'association_id_0',
bpmnElementName: 'association name',
bpmnElementSourceRefId: 'Activity_01',
bpmnElementTargetRefId: 'Annotation_01',
waypoints: [new Waypoint(362, 232)],
Expand All @@ -114,7 +110,6 @@ describe('parse bpmn as json for association', () => {
verifyEdge(model.edges[1], {
edgeId: 'edge_association_id_1',
bpmnElementId: 'association_id_1',
bpmnElementName: undefined,
bpmnElementSourceRefId: 'Activity_02',
bpmnElementTargetRefId: 'Annotation_02',
waypoints: [new Waypoint(362, 232)],
Expand Down Expand Up @@ -146,7 +141,6 @@ describe('parse bpmn as json for association', () => {
verifyEdge(model.edges[0], {
edgeId: `edge_association_id_0`,
bpmnElementId: `association_id_0`,
bpmnElementName: `association name`,
bpmnElementSourceRefId: 'Activity_01',
bpmnElementTargetRefId: 'Annotation_01',
waypoints: [new Waypoint(362, 232)],
Expand Down
2 changes: 1 addition & 1 deletion test/unit/component/parser/json/JsonTestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ExpectedShape {
interface ExpectedEdge {
edgeId: string;
bpmnElementId: string;
bpmnElementName: string;
bpmnElementName?: string;
bpmnElementSourceRefId: string;
bpmnElementTargetRefId: string;
waypoints: Waypoint[];
Expand Down