import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; import { add as collectionAdd } from 'diagram-js/lib/util/Collections'; import { remove as collectionRemove } from 'diagram-js/lib/util/Collections'; import IdGenerator from 'diagram-js/lib/util/IdGenerator'; var HIGH_PRIORITY = 1500; /** * This Command Intercetor functions like the BpmnUpdator in BPMN.js - It hooks into events * from Diagram.js and updates the underlying BPMN model accordingly. * * This handles the case where a new DataInput or DataOutput is added to * the diagram, it assures that a place exists for the new Data object to go, and it places it there. * There were a number of paces where I had to patch things in to get it to work correctly: * * Create a InputOutputSpecification on the BPMN Moddle if it doesn't exist. */ export default class IoInterceptor extends CommandInterceptor { constructor(eventBus, bpmnFactory, bpmnUpdater) { super(eventBus); this.execute([ 'shape.create' ], HIGH_PRIORITY, function(event) { let context = event.context; if ([ 'bpmn:DataInput', 'bpmn:DataOutput' ].includes(context.shape.type)) { let type = context.shape.type; let type_name = type.split(':')[1]; let process = context.parent.businessObject; let ioSpec = assureIOSpecificationExists(process, bpmnFactory); let di = context.shape.di; let generator = new IdGenerator(type_name), ioSpecification = process.get('ioSpecification'); let dataIO = bpmnFactory.create(type, { id: generator.next() }); context.shape.businessObject = dataIO; dataIO.$parent = ioSpec; di.businessObject = dataIO; di.bpmnElement = dataIO; context.shape.width = 36; // Default width is wrong. di.id = dataIO.id + 'DI'; bpmnUpdater.updateBounds(context.shape); if (type == 'bpmn:DataInput') { collectionAdd(ioSpecification.get('dataInputs'), dataIO); } else { collectionAdd(ioSpecification.get('dataOutputs'), dataIO); } } }); this.execute([ 'shape.delete' ], HIGH_PRIORITY, function(event) { let context = event.context; if ([ 'bpmn:DataInput', 'bpmn:DataOutput' ].includes(context.shape.type)) { let type = context.shape.type; let process = context.shape.parent.businessObject; let ioSpec = assureIOSpecificationExists(process, bpmnFactory); if (type == 'bpmn:DataInput') { collectionRemove(ioSpec.get('dataInputs'), context.shape.businessObject); } else { collectionRemove(ioSpec.get('dataOutputs'), context.shape.businessObject); } if (context.shape.di.$parent) { collectionRemove(context.shape.di.$parent.planeElement, context.shape.di); } } }); // Stop propagation on executed, to avoid the BpmnUpdator.js from causing errors. this.executed([ 'shape.delete', 'shape.create' ], HIGH_PRIORITY, function(event) { if ([ 'bpmn:DataInput', 'bpmn:DataOutput' ].includes(event.context.shape.type)) { event.stopPropagation(); // Don't let the main code execute, it will fail. } }); } } /** * * * * * * * @param process * @param bpmnFactory * @returns {bpmn:InputOutputSpecification} */ function assureIOSpecificationExists(process, bpmnFactory) { let ioSpecification = process.get('ioSpecification'); if (!ioSpecification) { // Create the BPMN ioSpecification = bpmnFactory.create('bpmn:InputOutputSpecification', { dataInputs: [], inputSets: [], dataOutputs: [], outputSets: [] }); ioSpecification.$parent = process; process.ioSpecification = ioSpecification; /* let inputSet = bpmnFactory.create('bpmn:InputSet', { dataInputRefs: [], name: 'Inputs' }); inputSet.$parent = ioSpecification; */ // collectionAdd(ioSpecification.get('inputSets'), inputSet); } return ioSpecification; } IoInterceptor.$inject = [ 'eventBus', 'bpmnFactory', 'bpmnUpdater' ];