'use strict'; import { some, isObject, isFunction } from '#/utils/min-dash.js'; var WILDCARD = '*'; export default function CamundaModdleExtension(eventBus) { var self = this; eventBus.on('moddleCopy.canCopyProperty', function(context) { var property = context.property; var parent = context.parent; return self.canCopyProperty(property, parent); }); } CamundaModdleExtension.$inject = ['eventBus']; /** * Check wether to disallow copying property. */ CamundaModdleExtension.prototype.canCopyProperty = function(property, parent) { // (1) check wether property is allowed in parent if (isObject(property) && !isAllowedInParent(property, parent)) { return false; } // (2) check more complex scenarios if (is(property, 'camunda:InputOutput') && !this.canHostInputOutput(parent)) { return false; } if (isAny(property, ['camunda:Connector', 'camunda:Field']) && !this.canHostConnector(parent)) { return false; } if (is(property, 'camunda:In') && !this.canHostIn(parent)) { return false; } }; CamundaModdleExtension.prototype.canHostInputOutput = function(parent) { // allowed in camunda:Connector var connector = getParent(parent, 'camunda:Connector'); if (connector) { return true; } // special rules inside bpmn:FlowNode var flowNode = getParent(parent, 'bpmn:FlowNode'); if (!flowNode) { return false; } if (isAny(flowNode, ['bpmn:StartEvent', 'bpmn:Gateway', 'bpmn:BoundaryEvent'])) { return false; } if (is(flowNode, 'bpmn:SubProcess') && flowNode.get('triggeredByEvent')) { return false; } return true; }; CamundaModdleExtension.prototype.canHostConnector = function(parent) { var serviceTaskLike = getParent(parent, 'camunda:ServiceTaskLike'); if (is(serviceTaskLike, 'bpmn:MessageEventDefinition')) { // only allow on throw and end events return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent'); } return true; }; CamundaModdleExtension.prototype.canHostIn = function(parent) { var callActivity = getParent(parent, 'bpmn:CallActivity'); if (callActivity) { return true; } var signalEventDefinition = getParent(parent, 'bpmn:SignalEventDefinition'); if (signalEventDefinition) { // only allow on throw and end events return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent'); } return true; }; // helpers ////////// function is(element, type) { return element && isFunction(element.$instanceOf) && element.$instanceOf(type); } function isAny(element, types) { return some(types, function(t) { return is(element, t); }); } function getParent(element, type) { if (!type) { return element.$parent; } if (is(element, type)) { return element; } if (!element.$parent) { return; } return getParent(element.$parent, type); } function isAllowedInParent(property, parent) { // (1) find property descriptor var descriptor = property.$type && property.$model.getTypeDescriptor(property.$type); var allowedIn = descriptor && descriptor.meta && descriptor.meta.allowedIn; if (!allowedIn || isWildcard(allowedIn)) { return true; } // (2) check wether property has parent of allowed type return some(allowedIn, function(type) { return getParent(parent, type); }); } function isWildcard(allowedIn) { return allowedIn.indexOf(WILDCARD) !== -1; }