From c3e0d6d16477bc2e9e37109a9ff1254b6695c7cc Mon Sep 17 00:00:00 2001 From: Philipp Fromme Date: Wed, 14 Apr 2021 11:11:32 +0200 Subject: [PATCH] fix: copy root element references Related to camunda/camunda-modeler#2185 --- .../behavior/BoundaryEventBehavior.js | 20 ++- .../modeling/behavior/BoundaryEvent.bpmn | 44 +++++- .../behavior/BoundaryEventBehaviorSpec.js | 130 +++++++++++++++++- 3 files changed, 188 insertions(+), 6 deletions(-) diff --git a/lib/features/modeling/behavior/BoundaryEventBehavior.js b/lib/features/modeling/behavior/BoundaryEventBehavior.js index 5b1c149b..00984b14 100644 --- a/lib/features/modeling/behavior/BoundaryEventBehavior.js +++ b/lib/features/modeling/behavior/BoundaryEventBehavior.js @@ -9,11 +9,13 @@ import { forEach } from 'min-dash'; +var HIGH_PRIORITY = 2000; + /** * BPMN specific boundary event behavior */ -export default function BoundaryEventBehavior(eventBus, modeling) { +export default function BoundaryEventBehavior(eventBus, moddle, modeling) { CommandInterceptor.call(this, eventBus); @@ -57,11 +59,25 @@ export default function BoundaryEventBehavior(eventBus, modeling) { }); } }); + + // copy reference to root element on replace + eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY, function(context) { + var parent = context.parent, + property = context.property, + propertyName = context.propertyName; + + var propertyDescriptor = moddle.getPropertyDescriptor(parent, propertyName); + + if (propertyDescriptor && propertyDescriptor.isReference && is(property, 'bpmn:RootElement')) { + parent.set(propertyName, property); + } + }); } BoundaryEventBehavior.$inject = [ 'eventBus', + 'moddle', 'modeling' ]; -inherits(BoundaryEventBehavior, CommandInterceptor); +inherits(BoundaryEventBehavior, CommandInterceptor); \ No newline at end of file diff --git a/test/spec/features/modeling/behavior/BoundaryEvent.bpmn b/test/spec/features/modeling/behavior/BoundaryEvent.bpmn index 2e995b54..46e10958 100644 --- a/test/spec/features/modeling/behavior/BoundaryEvent.bpmn +++ b/test/spec/features/modeling/behavior/BoundaryEvent.bpmn @@ -1,11 +1,31 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -14,11 +34,29 @@ + + + + + + + + + + + + + + + + + + - - + + diff --git a/test/spec/features/modeling/behavior/BoundaryEventBehaviorSpec.js b/test/spec/features/modeling/behavior/BoundaryEventBehaviorSpec.js index 2b668f16..29cdff48 100644 --- a/test/spec/features/modeling/behavior/BoundaryEventBehaviorSpec.js +++ b/test/spec/features/modeling/behavior/BoundaryEventBehaviorSpec.js @@ -6,6 +6,8 @@ import { import modelingModule from 'lib/features/modeling'; import coreModule from 'lib/core'; +import { is } from 'lib/util/ModelUtil'; + describe('features/modeling/behavior - boundary event', function() { @@ -61,4 +63,130 @@ describe('features/modeling/behavior - boundary event', function() { }); -}); \ No newline at end of file + + describe('copy reference on replace', function() { + + it('interrupting to non-interrupting', function() { + + it('should copy message reference', inject(function(bpmnReplace, elementRegistry) { + + // given + var interruptingBoundaryEvent = elementRegistry.get('BoundaryEvent_2'), + message = getReferencedRootElement(interruptingBoundaryEvent, 'messageRef'); + + // assume + expect(is(message, 'bpmn:Message')).to.be.true; + + // when + var nonInterruptingBoundaryEvent = bpmnReplace.replaceElement(interruptingBoundaryEvent, { + type: 'bpmn:BoundaryEvent', + eventDefinitionType: 'bpmn:MessageEventDefinition', + cancelActivity: false + }); + + // then + expect(getReferencedRootElement(nonInterruptingBoundaryEvent, 'messageRef')).to.equal(message); + })); + + + it('should copy escalation reference', inject(function(bpmnReplace, elementRegistry) { + + // given + var interruptingBoundaryEvent = elementRegistry.get('BoundaryEvent_3'), + escalation = getReferencedRootElement(interruptingBoundaryEvent, 'escalationRef'); + + // assume + expect(is(escalation, 'bpmn:Escalation')).to.be.true; + + // when + var nonInterruptingBoundaryEvent = bpmnReplace.replaceElement(interruptingBoundaryEvent, { + type: 'bpmn:BoundaryEvent', + eventDefinitionType: 'bpmn:EscalationEventDefinition', + cancelActivity: false + }); + + // then + expect(getReferencedRootElement(nonInterruptingBoundaryEvent, 'escalationRef')).to.equal(escalation); + })); + + + it('should copy error reference', inject(function(bpmnReplace, elementRegistry) { + + // given + var interruptingBoundaryEvent = elementRegistry.get('BoundaryEvent_4'), + error = getReferencedRootElement(interruptingBoundaryEvent, 'errorRef'); + + // assume + expect(is(error, 'bpmn:Error')).to.be.true; + + // when + var nonInterruptingBoundaryEvent = bpmnReplace.replaceElement(interruptingBoundaryEvent, { + type: 'bpmn:BoundaryEvent', + eventDefinitionType: 'bpmn:ErrorEventDefinition', + cancelActivity: false + }); + + // then + expect(getReferencedRootElement(nonInterruptingBoundaryEvent, 'errorRef')).to.equal(error); + })); + + + it('should copy signal reference', inject(function(bpmnReplace, elementRegistry) { + + // given + var interruptingBoundaryEvent = elementRegistry.get('BoundaryEvent_5'), + signal = getReferencedRootElement(interruptingBoundaryEvent, 'signalRef'); + + // assume + expect(is(signal, 'bpmn:Signal')).to.be.true; + + // when + var nonInterruptingBoundaryEvent = bpmnReplace.replaceElement(interruptingBoundaryEvent, { + type: 'bpmn:BoundaryEvent', + eventDefinitionType: 'bpmn:SignalEventDefinition', + cancelActivity: false + }); + + // then + expect(getReferencedRootElement(nonInterruptingBoundaryEvent, 'signalRef')).to.equal(signal); + })); + + }); + + + it('non-interrupting to interrupting', function() { + + it('should copy message reference', inject(function(bpmnReplace, elementRegistry) { + + // given + var interruptingBoundaryEvent = elementRegistry.get('BoundaryEvent_6'), + message = getReferencedRootElement(interruptingBoundaryEvent, 'messageRef'); + + // assume + expect(is(message, 'bpmn:Message')).to.be.true; + + // when + var nonInterruptingBoundaryEvent = bpmnReplace.replaceElement(interruptingBoundaryEvent, { + type: 'bpmn:BoundaryEvent', + eventDefinitionType: 'bpmn:MessageEventDefinition', + cancelActivity: true + }); + + // then + expect(getReferencedRootElement(nonInterruptingBoundaryEvent, 'messageRef')).to.equal(message); + })); + + }); + + }); + +}); + +// helpers ////////// + +function getReferencedRootElement(element, propertyName) { + var businessObject = element.businessObject, + eventDefinition = businessObject.eventDefinitions[ 0 ]; + + return eventDefinition.get(propertyName); +} \ No newline at end of file