import {BpmnTags, Model} from '@process-engine/process_engine_contracts'; import { getModelPropertyAsArray, setCommonObjectPropertiesFromData, } from '../type_factory'; import {parseProcessFlowNodes} from './flow_node_parser'; import {parseProcessLaneSet} from './process_lane_set_parser'; import {parseProcessSequenceFlows} from './sequence_flow_parser'; import * as moment from 'moment'; export function parseActivitiesFromProcessData(processData: any, errors: Array): Array { const manualTasks: Array = parseManualTasks(processData); const userTasks: Array = parseUserTasks(processData); const scriptTasks: Array = parseScriptTasks(processData); const serviceTasks: Array = parseServiceTasks(processData); const callActivities: Array = parseCallActivities(processData); const subProcesses: Array = parseSubProcesses(processData, errors); return Array.prototype.concat(manualTasks, userTasks, scriptTasks, serviceTasks, callActivities, subProcesses); } function parseManualTasks(processData: any): Array { const manualTasks: Array = []; const manualTasksRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.ManualTask); if (!manualTasksRaw || manualTasksRaw.length === 0) { return []; } for (const manualTaskRaw of manualTasksRaw) { const manualTask: Model.Activities.ManualTask = createActivityInstance(manualTaskRaw, Model.Activities.ManualTask); manualTasks.push(manualTask); } return manualTasks; } function parseUserTasks(processData: any): Array { const userTasks: Array = []; const userTasksRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.UserTask); if (!userTasksRaw || userTasksRaw.length === 0) { return []; } for (const userTaskRaw of userTasksRaw) { const userTask: Model.Activities.UserTask = createActivityInstance(userTaskRaw, Model.Activities.UserTask); userTask.assignee = userTaskRaw[BpmnTags.CamundaProperty.Assignee]; userTask.candidateUsers = userTaskRaw[BpmnTags.CamundaProperty.CandidateUsers]; userTask.candidateGroups = userTaskRaw[BpmnTags.CamundaProperty.CandidateGroups]; userTask.dueDate = parseDate(userTaskRaw[BpmnTags.CamundaProperty.DueDate]); userTask.followUpDate = parseDate(userTaskRaw[BpmnTags.CamundaProperty.FollowupDate]); userTask.formFields = parseFormFields(userTaskRaw); userTask.preferredControl = getPreferredControlForUserTask(userTaskRaw); userTasks.push(userTask); } function parseFormFields(userTaskRaw: any): Array { const extensionElements: any = userTaskRaw[BpmnTags.FlowElementProperty.ExtensionElements]; if (!extensionElements) { return []; } const formDataRaw: any = extensionElements[BpmnTags.CamundaProperty.FormData]; if (!formDataRaw) { return []; } const formFieldsRaw: any = getModelPropertyAsArray(formDataRaw, BpmnTags.CamundaProperty.FormField); if (!formFieldsRaw) { return []; } const formFields: Array = []; for (const formFieldRaw of formFieldsRaw) { const formField: Model.Types.FormField = parseFormField(formFieldRaw); formFields.push(formField); } return formFields; } function parseFormField(formFieldRaw: any): Model.Types.FormField { const formField: Model.Types.FormField = new Model.Types.FormField(); formField.id = formFieldRaw.id; formField.label = formFieldRaw.label; formField.type = formFieldRaw.type; formField.defaultValue = formFieldRaw.defaultValue; formField.preferredControl = formFieldRaw.preferredControl; if (formField.type === 'enum') { const rawValues: Array = getModelPropertyAsArray(formFieldRaw, BpmnTags.CamundaProperty.Value); const valueMapper: any = (enumValueRaw: any): Model.Types.EnumValue => { const enumValue: Model.Types.EnumValue = new Model.Types.EnumValue(); enumValue.id = enumValueRaw.id; enumValue.name = enumValueRaw.name; return enumValue; }; formField.enumValues = rawValues.map(valueMapper); } return formField; } function parseDate(value: string): Date { if (!value || value.length === 0 || !moment(value, 'YYYY-MM-DDTHH:mm:ss', true).isValid()) { return undefined; } const dateObj: moment.Moment = moment(value); return dateObj.toDate(); } return userTasks; } function parseScriptTasks(processData: any): Array { const scriptTasks: Array = []; const scriptTasksRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.ScriptTask); if (!scriptTasksRaw || scriptTasksRaw.length === 0) { return []; } for (const scriptTaskRaw of scriptTasksRaw) { const scriptTask: Model.Activities.ScriptTask = createActivityInstance(scriptTaskRaw, Model.Activities.ScriptTask); scriptTask.scriptFormat = scriptTaskRaw.scriptFormat; scriptTask.script = scriptTaskRaw[BpmnTags.FlowElementProperty.BpmnScript]; scriptTask.resultVariable = scriptTaskRaw[BpmnTags.CamundaProperty.ResultVariable]; scriptTasks.push(scriptTask); } return scriptTasks; } function parseServiceTasks(processData: any): Array { const serviceTasks: Array = []; const serviceTasksRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.ServiceTask); if (!serviceTasksRaw || serviceTasksRaw.length === 0) { return []; } for (const serviceTaskRaw of serviceTasksRaw) { const serviceTask: Model.Activities.ServiceTask = createActivityInstance(serviceTaskRaw, Model.Activities.ServiceTask); // Check if the extension properties contain invocations. if (serviceTask.extensionElements && serviceTask.extensionElements.camundaExtensionProperties && serviceTask.extensionElements.camundaExtensionProperties.length > 0) { const invocation: Model.Activities.Invocation = getInvocationForServiceTask(serviceTask); if (invocation) { serviceTask.invocation = invocation; } } serviceTasks.push(serviceTask); } return serviceTasks; } function getPreferredControlForUserTask(userTaskRaw: Model.Activities.UserTask): string { const extensionElements: any = userTaskRaw[BpmnTags.FlowElementProperty.ExtensionElements]; const extensionElementsIsNotExisting: boolean = extensionElements === undefined; if (extensionElementsIsNotExisting) { return; } const extensionPropertiesDataRaw: any = extensionElements[BpmnTags.CamundaProperty.Properties]; const extensionPropertiesDataIsNotExisting: boolean = extensionPropertiesDataRaw === undefined || extensionPropertiesDataRaw.length < 1; if (extensionPropertiesDataIsNotExisting) { return; } const extensionPropertiesRaw: any = extensionPropertiesDataRaw[BpmnTags.CamundaProperty.Property]; const extensionPropertiesAreNotExisting: boolean = extensionPropertiesRaw === undefined || extensionPropertiesRaw.length < 1; if (extensionPropertiesAreNotExisting) { return; } const extensionProperties: any = parseExtensionProperties(extensionPropertiesRaw); const preferredControlProperty: Model.Base.CamundaExtensionProperty = findExtensionPropertyByName('preferredControl', extensionProperties); const preferredControlPropertyIsNotExisting: boolean = preferredControlProperty === undefined; if (preferredControlPropertyIsNotExisting) { return; } return preferredControlProperty.value; } function parseExtensionProperties(extensionPropertiesRaw: any): any { const extensionProperties: Array = []; const extensionPropertiesIsNoArray: boolean = !Array.isArray(extensionPropertiesRaw); if (extensionPropertiesIsNoArray) { return [{name: extensionPropertiesRaw.name, value: extensionPropertiesRaw.value}]; } for (const extensionPropertyRaw of extensionPropertiesRaw) { const extensionProperty: Model.Base.CamundaExtensionProperty = {name: extensionPropertyRaw.name, value: extensionPropertyRaw.value}; extensionProperties.push(extensionProperty); } return extensionProperties; } function getInvocationForServiceTask(serviceTask: Model.Activities.ServiceTask): Model.Activities.Invocation { const extensionParameters: Array = serviceTask.extensionElements.camundaExtensionProperties; const methodInvocation: Model.Activities.MethodInvocation = getMethodInvocationForServiceTask(extensionParameters); if (!methodInvocation) { return getServiceInvocationForServiceTask(extensionParameters); } return methodInvocation; } function getMethodInvocationForServiceTask(extensionProperties: Array): Model.Activities.MethodInvocation { const methodInvocation: Model.Activities.MethodInvocation = new Model.Activities.MethodInvocation(); const moduleProperty: Model.Base.CamundaExtensionProperty = findExtensionPropertyByName('module', extensionProperties); const methodProperty: Model.Base.CamundaExtensionProperty = findExtensionPropertyByName('method', extensionProperties); const paramsProperty: Model.Base.CamundaExtensionProperty = findExtensionPropertyByName('params', extensionProperties); // If no module- or method- property is defined, this is not a valid method invocation, although parameters are optional. if (!moduleProperty || !methodProperty) { return undefined; } methodInvocation.module = moduleProperty.value; methodInvocation.method = methodProperty.value; methodInvocation.params = paramsProperty ? paramsProperty.value : '[]'; return methodInvocation; } function getServiceInvocationForServiceTask(extensionProperties: Array): Model.Activities.WebServiceInvocation { const serviceInvocation: Model.Activities.WebServiceInvocation = new Model.Activities.WebServiceInvocation(); const moduleProperty: Model.Base.CamundaExtensionProperty = findExtensionPropertyByName('service', extensionProperties); // If no service property is provided, this is not a valid web service invocation. if (!moduleProperty) { return undefined; } serviceInvocation.service = moduleProperty.value; return serviceInvocation; } function findExtensionPropertyByName( propertyName: string, extensionProperties: Array): Model.Base.CamundaExtensionProperty { return extensionProperties.find((property: Model.Base.CamundaExtensionProperty): boolean => { return property.name === propertyName; }); } function parseCallActivities(processData: any): Array { const callActivities: Array = []; const callActivitiesRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.CallActivity); if (!callActivitiesRaw || callActivitiesRaw.length === 0) { return []; } for (const callActivityRaw of callActivitiesRaw) { let callActivity: Model.Activities.CallActivity = createActivityInstance(callActivityRaw, Model.Activities.CallActivity); if (callActivityRaw.calledElement) { // NOTE: There is also a CMMN type, which is not supported yet. callActivity.type = Model.Activities.CallActivityType.BPMN; callActivity.calledReference = callActivityRaw.calledElement; callActivity.bindingType = callActivityRaw[BpmnTags.CamundaProperty.CalledElementBinding]; if (callActivity.bindingType === Model.Activities.CallActivityBindingType.version) { callActivity.calledElementVersion = callActivityRaw[BpmnTags.CamundaProperty.CalledElementVersion]; } callActivity.calledElementTenantId = callActivityRaw[BpmnTags.CamundaProperty.CalledElementTenantId]; callActivity = determineCallActivityMappingType(callActivity, callActivityRaw); } callActivities.push(callActivity); } return callActivities; } function parseSubProcesses(processData: any, errors: Array): Array { const subProcesses: Array = []; const subProcessesRaw: Array = getModelPropertyAsArray(processData, BpmnTags.TaskElement.SubProcess); if (!subProcessesRaw || subProcessesRaw.length === 0) { return []; } for (const subProcessRaw of subProcessesRaw) { const subProcess: Model.Activities.SubProcess = createActivityInstance(subProcessRaw, Model.Activities.SubProcess); subProcess.laneSet = parseProcessLaneSet(subProcessRaw); subProcess.flowNodes = parseProcessFlowNodes(subProcessRaw, errors); subProcess.sequenceFlows = parseProcessSequenceFlows(subProcessRaw); subProcesses.push(subProcess); } return subProcesses; } function determineCallActivityMappingType(callActivity: Model.Activities.CallActivity, data: any): Model.Activities.CallActivity { if (data[BpmnTags.CamundaProperty.VariableMappingClass]) { callActivity.delegateVariableMapping = Model.Activities.CallActivityDelegateVariableMapping.variableMappingClass; callActivity.variableMappingValue = data[BpmnTags.CamundaProperty.VariableMappingClass]; } else if (data[BpmnTags.CamundaProperty.VariableMappingDelegateExpression]) { callActivity.delegateVariableMapping = Model.Activities.CallActivityDelegateVariableMapping.variableMappingDelegateExpression; callActivity.variableMappingValue = data[BpmnTags.CamundaProperty.VariableMappingDelegateExpression]; } else { callActivity.delegateVariableMapping = Model.Activities.CallActivityDelegateVariableMapping.Unspecified; } return callActivity; } function createActivityInstance( data: any, type: Model.Base.IConstructor, ): TActivity { let instance: TActivity = new type(); instance = setCommonObjectPropertiesFromData(data, instance); instance.incoming = getModelPropertyAsArray(data, BpmnTags.FlowElementProperty.SequenceFlowIncoming) || []; instance.outgoing = getModelPropertyAsArray(data, BpmnTags.FlowElementProperty.SequenceFlowOutgoing) || []; instance.name = data.name; return instance; }