diff --git a/lib/camunda-cloud/CleanUpSubscriptionBehavior.js b/lib/camunda-cloud/CleanUpSubscriptionBehavior.js new file mode 100644 index 0000000..a3ddcc5 --- /dev/null +++ b/lib/camunda-cloud/CleanUpSubscriptionBehavior.js @@ -0,0 +1,85 @@ +import { + getBusinessObject, + is +} from 'bpmn-js/lib/util/ModelUtil'; + +import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; + +import { getExtensionElementsList, removeExtensionElements } from '../util/ExtensionElementsUtil'; + +/** + * Zeebe BPMN behavior ensuring that zeebe:subscription is removed from bpmn:Message + * when it has no properties anymore. + */ +export default class CleanUpSubscriptionBehavior extends CommandInterceptor { + constructor(eventBus, commandStack) { + super(eventBus); + + this.postExecuted([ + 'element.updateProperties', + 'element.updateModdleProperties' + ], context => { + const element = context.shape || context.newShape || context.element; + + if (element.labelTarget) { + return; + } + + if (!is(element, 'bpmn:Event')) { + return; + } + + const messageEventDefinition = getMessageEventDefinition(element); + + if (!messageEventDefinition) { + return; + } + + const message = messageEventDefinition.get('messageRef'); + + if (!message) { + return; + } + + const subscription = getSubscription(message); + + if (!subscription) { + return; + } + + if (!hasNoProperties(subscription)) { + return; + } + + removeExtensionElements(element, message, subscription, commandStack); + }, true); + } +} + +CleanUpSubscriptionBehavior.$inject = [ + 'eventBus', + 'commandStack' +]; + + +// helpers ////////// + +function getMessageEventDefinition(event) { + const businessObject = getBusinessObject(event); + + return businessObject.get('eventDefinitions').find(eventDefinition => { + return is(eventDefinition, 'bpmn:MessageEventDefinition'); + }); +} + +function getSubscription(message) { + return getExtensionElementsList(message, 'zeebe:Subscription')[ 0 ]; +} + +function hasNoProperties(element) { + const descriptor = element.$descriptor; + + return descriptor.properties.every(property => { + return element.get(property.name) === undefined; + }); +} diff --git a/lib/camunda-cloud/index.js b/lib/camunda-cloud/index.js index e46d206..a46bda6 100644 --- a/lib/camunda-cloud/index.js +++ b/lib/camunda-cloud/index.js @@ -1,5 +1,6 @@ import CleanUpBusinessRuleTaskBehavior from './CleanUpBusinessRuleTaskBehavior'; import CleanUpEndEventBehavior from './CleanUpEndEventBehavior'; +import CleanUpSubscriptionBehavior from './CleanUpSubscriptionBehavior'; import CleanUpTimerExpressionBehavior from './CleanUpTimerExpressionBehavior'; import CopyPasteBehavior from './CopyPasteBehavior'; import CreateZeebeCallActivityBehavior from './CreateZeebeCallActivityBehavior'; @@ -13,6 +14,7 @@ export default { __init__: [ 'cleanUpBusinessRuleTaskBehavior', 'cleanUpEndEventBehavior', + 'cleanUpSubscriptionBehavior', 'cleanUpTimerExpressionBehavior', 'copyPasteBehavior', 'createZeebeCallActivityBehavior', @@ -24,6 +26,7 @@ export default { ], cleanUpBusinessRuleTaskBehavior: [ 'type', CleanUpBusinessRuleTaskBehavior ], cleanUpEndEventBehavior: [ 'type', CleanUpEndEventBehavior ], + cleanUpSubscriptionBehavior: [ 'type', CleanUpSubscriptionBehavior ], cleanUpTimerExpressionBehavior: [ 'type', CleanUpTimerExpressionBehavior ], copyPasteBehavior: [ 'type', CopyPasteBehavior ], createZeebeCallActivityBehavior: [ 'type', CreateZeebeCallActivityBehavior ], diff --git a/test/camunda-cloud/CleanUpSubscriptionBehaviorSpec.js b/test/camunda-cloud/CleanUpSubscriptionBehaviorSpec.js new file mode 100644 index 0000000..95f5983 --- /dev/null +++ b/test/camunda-cloud/CleanUpSubscriptionBehaviorSpec.js @@ -0,0 +1,81 @@ +import { + bootstrapCamundaCloudModeler, + inject +} from 'test/TestHelper'; + +import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil'; + +import { getExtensionElementsList } from 'lib/util/ExtensionElementsUtil'; + +import diagramXML from './message-subscription.bpmn'; + + +describe('camunda-cloud/features/modeling - CleanUpSubscriptionBehavior', function() { + + beforeEach(bootstrapCamundaCloudModeler(diagramXML)); + + + describe('removing zeebe:subscription when correlationKey is removed', function() { + + let element; + + beforeEach(inject(function(elementRegistry, modeling) { + + // given + element = elementRegistry.get('Event'); + + const subscription = getSubscription(element); + + // when + modeling.updateModdleProperties(element, subscription, { + correlationKey: undefined + }); + })); + + + it('should execute', function() { + + // then + const subscription = getSubscription(element); + + expect(subscription).not.to.exist; + }); + + + it('should undo', inject(function(commandStack) { + + // when + commandStack.undo(); + + // then + const subscription = getSubscription(element); + + expect(subscription).to.exist; + expect(subscription.get('correlationKey')).to.equal('=abc'); + })); + + + it('should undo/redo', inject(function(commandStack) { + + // when + commandStack.undo(); + commandStack.redo(); + + // then + const subscription = getSubscription(element); + + expect(subscription).not.to.exist; + })); + + }); +}); + +// helpers ////////// + +function getSubscription(element) { + const businessObject = getBusinessObject(element); + const eventDefiniton = businessObject.get('eventDefinitions')[ 0 ]; + const message = eventDefiniton.get('messageRef'); + + return getExtensionElementsList(message, 'zeebe:Subscription')[ 0 ]; +} diff --git a/test/camunda-cloud/message-subscription.bpmn b/test/camunda-cloud/message-subscription.bpmn new file mode 100644 index 0000000..fcccdf8 --- /dev/null +++ b/test/camunda-cloud/message-subscription.bpmn @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +