import { getBusinessObject, getDi, is } from '../../util/ModelUtil'; import { forEach, isArray, isUndefined, omit, reduce } from 'min-dash'; function copyProperties(source, target, properties) { if (!isArray(properties)) { properties = [ properties ]; } forEach(properties, function(property) { if (!isUndefined(source[property])) { target[property] = source[property]; } }); } var LOW_PRIORITY = 750; export default function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) { function copy(bo, clone) { var targetBo = bpmnFactory.create(bo.$type); return moddleCopy.copyElement(bo, targetBo, null, clone); } eventBus.on('copyPaste.copyElement', LOW_PRIORITY, function(context) { var descriptor = context.descriptor, element = context.element, businessObject = getBusinessObject(element); // do not copy business object + di for labels; // will be pulled from the referenced label target if (isLabel(element)) { return descriptor; } var businessObjectCopy = descriptor.businessObject = copy(businessObject, true); var diCopy = descriptor.di = copy(getDi(element), true); diCopy.bpmnElement = businessObjectCopy; copyProperties(businessObjectCopy, descriptor, 'name'); copyProperties(diCopy, descriptor, 'isExpanded'); // default sequence flow if (businessObject.default) { descriptor.default = businessObject.default.id; } }); var referencesKey = '-bpmn-js-refs'; function getReferences(cache) { return (cache[referencesKey] = cache[referencesKey] || {}); } function setReferences(cache, references) { cache[referencesKey] = references; } function resolveReferences(descriptor, cache, references) { var businessObject = getBusinessObject(descriptor); // default sequence flows if (descriptor.default) { // relationship cannot be resolved immediately references[ descriptor.default ] = { element: businessObject, property: 'default' }; } // boundary events if (descriptor.host) { // relationship can be resolved immediately getBusinessObject(descriptor).attachedToRef = getBusinessObject(cache[ descriptor.host ]); } return omit(references, reduce(references, function(array, reference, key) { var element = reference.element, property = reference.property; if (key === descriptor.id) { element[ property ] = businessObject; array.push(descriptor.id); } return array; }, [])); } eventBus.on('copyPaste.pasteElement', function(context) { var cache = context.cache, descriptor = context.descriptor, businessObject = descriptor.businessObject, di = descriptor.di; // wire existing di + businessObject for external label if (isLabel(descriptor)) { descriptor.businessObject = getBusinessObject(cache[ descriptor.labelTarget ]); descriptor.di = getDi(cache[ descriptor.labelTarget ]); return; } businessObject = descriptor.businessObject = copy(businessObject); di = descriptor.di = copy(di); di.bpmnElement = businessObject; copyProperties(descriptor, businessObject, [ 'isExpanded', 'name' ]); descriptor.type = businessObject.$type; }); // copy + paste processRef with participant eventBus.on('copyPaste.copyElement', LOW_PRIORITY, function(context) { var descriptor = context.descriptor, element = context.element; if (!is(element, 'bpmn:Participant')) { return; } var participantBo = getBusinessObject(element); if (participantBo.processRef) { descriptor.processRef = copy(participantBo.processRef, true); } }); eventBus.on('copyPaste.pasteElement', function(context) { var descriptor = context.descriptor, processRef = descriptor.processRef; if (processRef) { descriptor.processRef = copy(processRef); } }); // resolve references eventBus.on('copyPaste.pasteElement', LOW_PRIORITY, function(context) { var cache = context.cache, descriptor = context.descriptor; // resolve references e.g. default sequence flow setReferences( cache, resolveReferences(descriptor, cache, getReferences(cache)) ); }); } BpmnCopyPaste.$inject = [ 'bpmnFactory', 'eventBus', 'moddleCopy' ]; // helpers ////////// function isLabel(element) { return !!element.labelTarget; }