Skip to content

Commit 8dafb95

Browse files
committed
WIP: feat: template linkedResources
1 parent d9dcc09 commit 8dafb95

File tree

6 files changed

+352
-8
lines changed

6 files changed

+352
-8
lines changed

src/cloud-element-templates/cmd/ChangeElementTemplateHandler.js

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import {
3333
MESSAGE_PROPERTY_TYPE,
3434
MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE,
3535
TASK_DEFINITION_TYPES,
36-
ZEEBE_CALLED_ELEMENT
36+
ZEEBE_CALLED_ELEMENT,
37+
ZEEBE_LINKED_RESOURCE_PROPERTY
3738
} from '../util/bindingTypes';
3839

3940
import {
@@ -107,6 +108,8 @@ export default class ChangeElementTemplateHandler {
107108
this._updateMessage(element, oldTemplate, newTemplate);
108109

109110
this._updateCalledElement(element, oldTemplate, newTemplate);
111+
112+
this._updateLinkedResources(element, oldTemplate, newTemplate);
110113
}
111114
}
112115

@@ -1032,6 +1035,118 @@ export default class ChangeElementTemplateHandler {
10321035

10331036
return replacedElement;
10341037
}
1038+
1039+
1040+
_updateLinkedResources(element, oldTemplate, newTemplate) {
1041+
const bpmnFactory = this._bpmnFactory,
1042+
commandStack = this._commandStack;
1043+
1044+
const newLinkedResources = newTemplate.properties.filter((newProperty) => {
1045+
const newBinding = newProperty.binding,
1046+
newBindingType = newBinding.type;
1047+
1048+
return newBindingType === 'zeebe:linkedResource#property';
1049+
});
1050+
1051+
const extensionElements = this._getOrCreateExtensionElements(element);
1052+
1053+
let linkedResources = findExtension(extensionElements, 'zeebe:LinkedResources');
1054+
1055+
// (1) remove linkedResourcess if no new specified
1056+
if (!newLinkedResources.length) {
1057+
if (!linkedResources) {
1058+
return;
1059+
}
1060+
1061+
commandStack.execute('element.updateModdleProperties', {
1062+
element,
1063+
moddleElement: extensionElements,
1064+
properties: {
1065+
values: without(extensionElements.get('values'), linkedResources)
1066+
}
1067+
});
1068+
return;
1069+
}
1070+
1071+
if (!linkedResources) {
1072+
linkedResources = bpmnFactory.create('zeebe:LinkedResources');
1073+
1074+
linkedResources.$parent = extensionElements;
1075+
1076+
commandStack.execute('element.updateModdleProperties', {
1077+
element,
1078+
moddleElement: extensionElements,
1079+
properties: {
1080+
values: [ ...extensionElements.get('values'), linkedResources ]
1081+
}
1082+
});
1083+
}
1084+
1085+
const oldLinkedResources = linkedResources.get('values')?.slice() || [];
1086+
1087+
newLinkedResources.forEach((newLinkedResource) => {
1088+
const oldProperty = findOldProperty(oldTemplate, newLinkedResource),
1089+
oldLinkedResource = findBusinessObject(extensionElements, newLinkedResource),
1090+
newPropertyValue = getDefaultValue(newLinkedResource),
1091+
newBinding = newLinkedResource.binding;
1092+
1093+
// (2) update old LinkesResources
1094+
if (oldLinkedResource) {
1095+
1096+
// debugger;
1097+
console.log(oldLinkedResource, oldLinkedResource, oldProperty, newLinkedResource, shouldKeepValue(oldLinkedResource, oldProperty, newLinkedResource));
1098+
1099+
if (
1100+
shouldUpdate(newPropertyValue, newLinkedResource)
1101+
|| shouldKeepValue(oldLinkedResource, oldProperty, newLinkedResource)
1102+
) {
1103+
remove(oldLinkedResources, oldLinkedResource);
1104+
}
1105+
1106+
if (!shouldKeepValue(oldLinkedResource, oldProperty, newLinkedResource)) {
1107+
commandStack.execute('element.updateModdleProperties', {
1108+
element,
1109+
moddleElement: oldLinkedResource,
1110+
properties: {
1111+
[newBinding.property]: newPropertyValue
1112+
}
1113+
});
1114+
}
1115+
}
1116+
1117+
// (3) add new linkedResources
1118+
else if (shouldUpdate(newPropertyValue, newLinkedResource)) {
1119+
const newProperties = {
1120+
linkName: newBinding.linkName,
1121+
[newBinding.property]: newPropertyValue
1122+
};
1123+
1124+
const newLinkedResource = createElement('zeebe:LinkedResource', newProperties, extensionElements, bpmnFactory);
1125+
1126+
commandStack.execute('element.updateModdleProperties', {
1127+
element,
1128+
moddleElement: linkedResources,
1129+
properties: {
1130+
values: [ ...linkedResources.get('values'), newLinkedResource ]
1131+
}
1132+
});
1133+
}
1134+
});
1135+
1136+
1137+
// (4) remove old linkedResources
1138+
// TODO: remove single properties as well as complete linkedResources elements
1139+
if (oldLinkedResources.length) {
1140+
commandStack.execute('element.updateModdleProperties', {
1141+
element,
1142+
moddleElement: linkedResources,
1143+
properties: {
1144+
properties: without(linkedResources.get('values'), linkedResource => oldLinkedResources.includes(linkedResource))
1145+
}
1146+
});
1147+
}
1148+
}
1149+
10351150
}
10361151

10371152
ChangeElementTemplateHandler.$inject = [
@@ -1106,6 +1221,18 @@ function findBusinessObject(element, property) {
11061221
return value.get('name') === binding.name;
11071222
});
11081223
}
1224+
1225+
if (bindingType === ZEEBE_LINKED_RESOURCE_PROPERTY) {
1226+
const linkedResources = findExtension(businessObject, 'zeebe:LinkedResources');
1227+
1228+
if (!linkedResources) {
1229+
return;
1230+
}
1231+
1232+
return linkedResources.get('values').find((value) => {
1233+
return value.get('linkName') === binding.linkName;
1234+
});
1235+
}
11091236
}
11101237

11111238
/**
@@ -1224,6 +1351,19 @@ export function findOldProperty(oldTemplate, newProperty) {
12241351
return oldBinding.name === newBinding.name;
12251352
});
12261353
}
1354+
1355+
if (newBindingType === ZEEBE_LINKED_RESOURCE_PROPERTY) {
1356+
return oldProperties.find(oldProperty => {
1357+
const oldBinding = oldProperty.binding,
1358+
oldBindingType = oldBinding.type;
1359+
1360+
if (oldBindingType !== ZEEBE_LINKED_RESOURCE_PROPERTY) {
1361+
return;
1362+
}
1363+
1364+
return oldBinding.linkName === newBinding.linkName && oldBinding.property === newBinding.property;
1365+
});
1366+
}
12271367
}
12281368

12291369
/**
@@ -1289,7 +1429,8 @@ function getPropertyValue(element, property) {
12891429

12901430
const binding = property.binding,
12911431
bindingName = binding.name,
1292-
bindingType = binding.type;
1432+
bindingType = binding.type,
1433+
bindingProperty = binding.property;
12931434

12941435

12951436
if (bindingType === 'property') {
@@ -1323,6 +1464,10 @@ function getPropertyValue(element, property) {
13231464
if (bindingType === MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE) {
13241465
return businessObject.get(bindingName);
13251466
}
1467+
1468+
if (bindingType === ZEEBE_LINKED_RESOURCE_PROPERTY) {
1469+
return businessObject.get(bindingProperty);
1470+
}
13261471
}
13271472

13281473
function remove(array, item) {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
2+
import { createElement } from '../../utils/ElementUtil';
3+
import {
4+
ensureExtension
5+
} from '../CreateHelper';
6+
import { getDefaultValue } from '../Helper';
7+
8+
import {
9+
getTaskDefinitionPropertyName
10+
} from '../util/taskDefinition';
11+
12+
13+
export default class LinkedResourcePropertyBindingProvider {
14+
static create(element, options) {
15+
const {
16+
property,
17+
bpmnFactory
18+
} = options;
19+
20+
const {
21+
binding: {
22+
property: bindingProperty,
23+
linkName
24+
}
25+
} = property;
26+
27+
const value = getDefaultValue(property);
28+
29+
const bo = getBusinessObject(element);
30+
const linkedResources = ensureExtension(element, 'zeebe:LinkedResources', bpmnFactory);
31+
32+
let linkedResource = linkedResources.get('values').find(linkedResource => linkedResource.get('linkName') === linkName);
33+
34+
if (!linkedResource) {
35+
linkedResource = createElement('zeebe:LinkedResource', { linkName }, bo, bpmnFactory);
36+
linkedResources.get('values').push(linkedResource);
37+
}
38+
39+
linkedResource.set(bindingProperty, value);
40+
}
41+
}

src/cloud-element-templates/create/TemplateElementFactory.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ZeebePropertiesProvider from './ZeebePropertiesProvider';
1313
import { MessagePropertyBindingProvider } from './MessagePropertyBindingProvider';
1414
import { MessageZeebeSubscriptionBindingProvider } from './MessageZeebeSubscriptionBindingProvider';
1515
import { CalledElementBindingProvider } from './CalledElementBindingProvider';
16+
import LinkedResourcePropertyBindingProvider from './LinkedResourceProvider';
1617

1718
import {
1819
MESSAGE_PROPERTY_TYPE,
@@ -24,7 +25,8 @@ import {
2425
ZEEBE_OUTPUT_TYPE,
2526
ZEEBE_TASK_HEADER_TYPE,
2627
ZEBBE_PROPERTY_TYPE,
27-
ZEEBE_CALLED_ELEMENT
28+
ZEEBE_CALLED_ELEMENT,
29+
ZEEBE_LINKED_RESOURCE_PROPERTY
2830
} from '../util/bindingTypes';
2931

3032
import {
@@ -47,7 +49,8 @@ export default class TemplateElementFactory {
4749
[ZEEBE_TASK_HEADER_TYPE]: TaskHeaderBindingProvider,
4850
[MESSAGE_PROPERTY_TYPE]: MessagePropertyBindingProvider,
4951
[MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE]: MessageZeebeSubscriptionBindingProvider,
50-
[ZEEBE_CALLED_ELEMENT]: CalledElementBindingProvider
52+
[ZEEBE_CALLED_ELEMENT]: CalledElementBindingProvider,
53+
[ZEEBE_LINKED_RESOURCE_PROPERTY]: LinkedResourcePropertyBindingProvider
5154
};
5255
}
5356

src/cloud-element-templates/util/bindingTypes.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const ZEEBE_TASK_HEADER_TYPE = 'zeebe:taskHeader';
1010
export const MESSAGE_PROPERTY_TYPE = 'bpmn:Message#property';
1111
export const MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE = 'bpmn:Message#zeebe:subscription#property';
1212
export const ZEEBE_CALLED_ELEMENT = 'zeebe:calledElement';
13+
export const ZEEBE_LINKED_RESOURCE_PROPERTY = 'zeebe:linkedResource#property';
1314

1415
export const EXTENSION_BINDING_TYPES = [
1516
MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE,
@@ -19,7 +20,8 @@ export const EXTENSION_BINDING_TYPES = [
1920
ZEEBE_TASK_DEFINITION_TYPE_TYPE,
2021
ZEEBE_TASK_DEFINITION,
2122
ZEEBE_TASK_HEADER_TYPE,
22-
ZEEBE_CALLED_ELEMENT
23+
ZEEBE_CALLED_ELEMENT,
24+
ZEEBE_LINKED_RESOURCE_PROPERTY
2325
];
2426

2527
export const TASK_DEFINITION_TYPES = [

src/cloud-element-templates/util/propertyUtil.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import {
2222
ZEEBE_OUTPUT_TYPE,
2323
ZEEBE_PROPERTY_TYPE,
2424
ZEEBE_TASK_HEADER_TYPE,
25-
ZEEBE_CALLED_ELEMENT
25+
ZEEBE_CALLED_ELEMENT,
26+
ZEEBE_LINKED_RESOURCE_PROPERTY
2627
} from './bindingTypes';
2728

2829
import {
@@ -81,7 +82,8 @@ function getRawPropertyValue(element, property, scope) {
8182
const {
8283
name,
8384
property: bindingProperty,
84-
type
85+
type,
86+
linkName
8587
} = binding;
8688

8789
// property
@@ -210,6 +212,18 @@ function getRawPropertyValue(element, property, scope) {
210212
return calledElement ? calledElement.get(bindingProperty) : defaultValue;
211213
}
212214

215+
if (type === ZEEBE_LINKED_RESOURCE_PROPERTY) {
216+
const linkedResources = findExtension(businessObject, 'zeebe:LinkedResources');
217+
218+
if (!linkedResources) {
219+
return defaultValue;
220+
}
221+
222+
const linkedResource = linkedResources.get('values').find((value) => value.get('linkName') === linkName);
223+
224+
return linkedResource ? linkedResource.get(bindingProperty) : defaultValue;
225+
}
226+
213227
// should never throw as templates are validated beforehand
214228
throw unknownBindingError(element, property);
215229
}
@@ -242,7 +256,9 @@ export function setPropertyValue(bpmnFactory, commandStack, element, property, v
242256

243257
const {
244258
name,
245-
type
259+
type,
260+
property: bindingProperty,
261+
linkName
246262
} = binding;
247263

248264
let extensionElements;
@@ -593,6 +609,47 @@ export function setPropertyValue(bpmnFactory, commandStack, element, property, v
593609
}
594610
}
595611

612+
if (type === ZEEBE_LINKED_RESOURCE_PROPERTY) {
613+
let linkedResources = findExtension(businessObject, 'zeebe:LinkedResources');
614+
615+
if (!linkedResources) {
616+
linkedResources = createElement('zeebe:LinkedResources', null, businessObject, bpmnFactory);
617+
618+
commands.push({
619+
cmd: 'element.updateModdleProperties',
620+
context: {
621+
...context,
622+
moddleElement: extensionElements,
623+
properties: { values: [ ...extensionElements.get('values'), linkedResources ] }
624+
}
625+
});
626+
}
627+
628+
let linkedResource = linkedResources.get('values').find((value) => value.get('linkName') === linkName);
629+
630+
if (!linkedResource) {
631+
linkedResource = createElement('zeebe:LinkedResource', { linkName }, businessObject, bpmnFactory);
632+
633+
commands.push({
634+
cmd: 'element.updateModdleProperties',
635+
context: {
636+
...context,
637+
moddleElement: linkedResources,
638+
properties: { values: [ ...linkedResources.get('values'), linkedResource ] }
639+
}
640+
});
641+
}
642+
643+
commands.push({
644+
cmd: 'element.updateModdleProperties',
645+
context: {
646+
...context,
647+
moddleElement: linkedResource,
648+
properties: { [ bindingProperty ]: value }
649+
}
650+
});
651+
}
652+
596653
if (commands.length) {
597654
const commandsToExecute = commands.filter((command) => command !== NO_OP);
598655

0 commit comments

Comments
 (0)