@jylups/cmmn-js 0.0.0-stage → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/.babelrc +3 -0
  2. package/CHANGELOG.md +119 -0
  3. package/LICENSE +23 -0
  4. package/README.md +107 -2
  5. package/dist/assets/cmmn-font/css/cmmn-codes.css +41 -0
  6. package/dist/assets/cmmn-font/css/cmmn-embedded.css +94 -0
  7. package/dist/assets/cmmn-font/css/cmmn.css +97 -0
  8. package/dist/assets/cmmn-font/font/cmmn.eot +0 -0
  9. package/dist/assets/cmmn-font/font/cmmn.svg +90 -0
  10. package/dist/assets/cmmn-font/font/cmmn.ttf +0 -0
  11. package/dist/assets/cmmn-font/font/cmmn.woff +0 -0
  12. package/dist/assets/cmmn-font/font/cmmn.woff2 +0 -0
  13. package/dist/assets/diagram-js.css +713 -0
  14. package/dist/cmmn-modeler.development.js +44817 -0
  15. package/dist/cmmn-modeler.production.min.js +2 -0
  16. package/dist/cmmn-navigated-viewer.development.js +18131 -0
  17. package/dist/cmmn-navigated-viewer.production.min.js +2 -0
  18. package/dist/cmmn-viewer.development.js +17599 -0
  19. package/dist/cmmn-viewer.production.min.js +2 -0
  20. package/index.js +1 -0
  21. package/lib/Modeler.js +222 -0
  22. package/lib/NavigatedViewer.js +28 -0
  23. package/lib/Viewer.js +489 -0
  24. package/lib/core/ItemRegistry.js +316 -0
  25. package/lib/core/index.js +7 -0
  26. package/lib/draw/CmmnRenderer.js +1235 -0
  27. package/lib/draw/PathMap.js +335 -0
  28. package/lib/draw/index.js +5 -0
  29. package/lib/features/auto-resize/CmmnAutoResizeProvider.js +57 -0
  30. package/lib/features/auto-resize/index.js +7 -0
  31. package/lib/features/context-pad/ContextPadProvider.js +240 -0
  32. package/lib/features/context-pad/index.js +11 -0
  33. package/lib/features/editor-actions/CmmnEditorActions.js +105 -0
  34. package/lib/features/editor-actions/index.js +10 -0
  35. package/lib/features/keyboard/CmmnKeyboardBindings.js +159 -0
  36. package/lib/features/keyboard/index.js +7 -0
  37. package/lib/features/label-editing/LabelEditingProvider.js +221 -0
  38. package/lib/features/label-editing/LabelUtil.js +95 -0
  39. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +63 -0
  40. package/lib/features/label-editing/index.js +9 -0
  41. package/lib/features/modeling/CmmnFactory.js +166 -0
  42. package/lib/features/modeling/CmmnLayouter.js +49 -0
  43. package/lib/features/modeling/CmmnUpdater.js +511 -0
  44. package/lib/features/modeling/ElementFactory.js +215 -0
  45. package/lib/features/modeling/Modeling.js +185 -0
  46. package/lib/features/modeling/behavior/AttachCriterionBehavior.js +58 -0
  47. package/lib/features/modeling/behavior/CaseFileItemUpdater.js +324 -0
  48. package/lib/features/modeling/behavior/LabelBehavior.js +139 -0
  49. package/lib/features/modeling/behavior/PlanItemDefinitionUpdater.js +449 -0
  50. package/lib/features/modeling/behavior/PlanningTableUpdater.js +620 -0
  51. package/lib/features/modeling/behavior/ReplaceConnectionBehavior.js +320 -0
  52. package/lib/features/modeling/behavior/ReplaceElementBehavior.js +395 -0
  53. package/lib/features/modeling/behavior/ResizeCasePlanModelBehavior.js +108 -0
  54. package/lib/features/modeling/behavior/SentryUpdater.js +678 -0
  55. package/lib/features/modeling/behavior/UnclaimIdBehavior.js +28 -0
  56. package/lib/features/modeling/behavior/index.js +24 -0
  57. package/lib/features/modeling/cmd/AppendShapeHandler.js +52 -0
  58. package/lib/features/modeling/cmd/IdClaimHandler.js +38 -0
  59. package/lib/features/modeling/cmd/ReconnectConnectionHandler.js +57 -0
  60. package/lib/features/modeling/cmd/ReplaceShapeHandler.js +46 -0
  61. package/lib/features/modeling/cmd/UpdateControlsHandler.js +221 -0
  62. package/lib/features/modeling/cmd/UpdatePropertiesHandler.js +240 -0
  63. package/lib/features/modeling/cmd/UpdateSemanticParentHandler.js +94 -0
  64. package/lib/features/modeling/index.js +20 -0
  65. package/lib/features/modeling/util/ModelingUtil.js +138 -0
  66. package/lib/features/modeling/util/PlanItemDefinitionUtil.js +183 -0
  67. package/lib/features/ordering/CmmnOrderingProvider.js +146 -0
  68. package/lib/features/ordering/index.js +4 -0
  69. package/lib/features/outline/Outline.js +47 -0
  70. package/lib/features/outline/index.js +6 -0
  71. package/lib/features/palette/PaletteProvider.js +171 -0
  72. package/lib/features/palette/index.js +12 -0
  73. package/lib/features/popup-menu/ReplaceMenuProvider.js +448 -0
  74. package/lib/features/popup-menu/index.js +4 -0
  75. package/lib/features/replace/CmmnReplace.js +355 -0
  76. package/lib/features/replace/ReplaceOptions.js +241 -0
  77. package/lib/features/replace/index.js +8 -0
  78. package/lib/features/replace-preview/CmmnReplacePreview.js +247 -0
  79. package/lib/features/replace-preview/index.js +7 -0
  80. package/lib/features/rules/CmmnRules.js +1040 -0
  81. package/lib/features/rules/index.js +7 -0
  82. package/lib/features/search/CmmnSearchProvider.js +129 -0
  83. package/lib/features/search/index.js +7 -0
  84. package/lib/features/snapping/CmmnConnectSnapping.js +110 -0
  85. package/lib/features/snapping/CmmnCreateMoveSnapping.js +148 -0
  86. package/lib/features/snapping/CmmnResizeSnapping.js +42 -0
  87. package/lib/features/snapping/CmmnSnappingUtil.js +76 -0
  88. package/lib/features/snapping/index.js +17 -0
  89. package/lib/import/CmmnImporter.js +251 -0
  90. package/lib/import/CmmnTreeWalker.js +410 -0
  91. package/lib/import/Importer.js +73 -0
  92. package/lib/import/Util.js +9 -0
  93. package/lib/import/index.js +3 -0
  94. package/lib/util/DiUtil.js +39 -0
  95. package/lib/util/LabelUtil.js +124 -0
  96. package/lib/util/ModelUtil.js +257 -0
  97. package/lib/util/PoweredByUtil.js +91 -0
  98. package/package.json +88 -4
  99. package/test/helper/index.js +231 -0
  100. package/test/util/KeyEvents.js +23 -0
  101. package/test/util/MockEvents.js +55 -0
  102. package/test/util/custom-rules/CustomRules.js +19 -0
  103. package/test/util/custom-rules/index.js +4 -0
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ var map = require('min-dash').map,
4
+ assign = require('min-dash').assign,
5
+ pick = require('min-dash').pick;
6
+
7
+ var isAny = require('./util/ModelingUtil').isAny;
8
+
9
+ function CmmnFactory(moddle) {
10
+ this._model = moddle;
11
+ }
12
+
13
+ CmmnFactory.$inject = [ 'moddle' ];
14
+
15
+
16
+ CmmnFactory.prototype._needsId = function(element) {
17
+ return isAny(element, [
18
+ 'cmmn:CMMNElement',
19
+ 'cmmndi:CMMNShape',
20
+ 'cmmndi:CMMNEdge',
21
+ 'cmmndi:CMMNStyle',
22
+ 'cmmndi:CMMNDiagram'
23
+ ]);
24
+ };
25
+
26
+ CmmnFactory.prototype._ensureId = function(element) {
27
+ // generate semantic ids for elements
28
+ var prefix = (element.$type || '').replace(/^[^:]*:/g, '') + '_';
29
+
30
+ if (!element.id && this._needsId(element)) {
31
+ element.id = this._model.ids.nextPrefixed(prefix, element);
32
+ }
33
+ };
34
+
35
+
36
+ CmmnFactory.prototype.create = function(type, attrs) {
37
+ var element = this._model.create(type, attrs || {});
38
+
39
+ this._ensureId(element);
40
+
41
+ return element;
42
+ };
43
+
44
+
45
+ CmmnFactory.prototype.createDiLabel = function() {
46
+ return this.create('cmmndi:CMMNLabel');
47
+ };
48
+
49
+
50
+ CmmnFactory.prototype.createDiShape = function(semantic, bounds, attrs) {
51
+ return this.create('cmmndi:CMMNShape', assign({
52
+ cmmnElementRef: semantic,
53
+ bounds: this.createDiBounds(bounds),
54
+ label: this.createDiLabel()
55
+ }, attrs));
56
+ };
57
+
58
+
59
+ CmmnFactory.prototype.createDiEdge = function(semantic, waypoints, attrs) {
60
+ return this.create('cmmndi:CMMNEdge', assign({
61
+ cmmnElementRef: semantic,
62
+ label: this.createDiLabel()
63
+ }, attrs));
64
+ };
65
+
66
+
67
+ CmmnFactory.prototype.createDiBounds = function(bounds) {
68
+ return this.create('dc:Bounds', bounds);
69
+ };
70
+
71
+
72
+ CmmnFactory.prototype.createDiWaypoints = function(waypoints) {
73
+
74
+ var self = this;
75
+
76
+ return map(waypoints, function(pos) {
77
+ return self.createDiWaypoint(pos);
78
+ });
79
+ };
80
+
81
+
82
+ CmmnFactory.prototype.createDiWaypoint = function(point) {
83
+ return this.create('dc:Point', pick(point, [ 'x', 'y' ]));
84
+ };
85
+
86
+
87
+ CmmnFactory.prototype.createItem = function(itemType, definitionType) {
88
+
89
+ var definition = this.create(definitionType);
90
+
91
+ return this.create(itemType, {
92
+ definitionRef: definition
93
+ });
94
+ };
95
+
96
+
97
+ CmmnFactory.prototype.createCriterion = function(criterionType, attrs) {
98
+
99
+ attrs = attrs || {};
100
+
101
+ if (!attrs.sentryRef) {
102
+ attrs = assign({
103
+ sentryRef: this.createSentry()
104
+ }, attrs);
105
+ }
106
+
107
+ return this.create(criterionType, attrs);
108
+ };
109
+
110
+
111
+ CmmnFactory.prototype.createSentry = function(attrs) {
112
+ return this.create('cmmn:Sentry', attrs);
113
+ };
114
+
115
+
116
+ CmmnFactory.prototype.createCasePlanModel = function() {
117
+
118
+ var casePlanModel = this.create('cmmn:Stage');
119
+
120
+ // overwrite generated id to 'CasePlanModel_...'
121
+ this._model.ids.unclaim(casePlanModel.id);
122
+ casePlanModel.id = this._model.ids.nextPrefixed('CasePlanModel_', casePlanModel);
123
+
124
+ var _case = this.create('cmmn:Case', {
125
+ casePlanModel: casePlanModel
126
+ });
127
+
128
+ casePlanModel.$parent = _case;
129
+
130
+ return casePlanModel;
131
+
132
+ };
133
+
134
+
135
+ CmmnFactory.prototype.createCaseFileModel = function(_case) {
136
+
137
+ var caseFileModel = this.create('cmmn:CaseFile');
138
+
139
+ // overwrite generated id to 'CaseFileModel_...'
140
+ this._model.ids.unclaim(caseFileModel.id);
141
+ caseFileModel.id = this._model.ids.nextPrefixed('CaseFileModel_', caseFileModel);
142
+
143
+ caseFileModel.$parent = _case;
144
+
145
+ return caseFileModel;
146
+
147
+ };
148
+
149
+
150
+ CmmnFactory.prototype.createCaseFileItem = function(attrs) {
151
+
152
+ attrs = attrs || {};
153
+
154
+ if (!attrs.definitionRef) {
155
+
156
+ attrs = assign({
157
+ definitionRef: this.create('cmmn:CaseFileItemDefinition')
158
+ }, attrs);
159
+
160
+ }
161
+
162
+ return this.create('cmmn:CaseFileItem', attrs);
163
+
164
+ };
165
+
166
+ module.exports = CmmnFactory;
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ var inherits = require('inherits');
4
+
5
+ var BaseLayouter = require('diagram-js/lib/layout/BaseLayouter').default,
6
+ ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout');
7
+
8
+ var getMid = require('diagram-js/lib/layout/LayoutUtil').getMid;
9
+
10
+
11
+ function CmmnLayouter() {}
12
+
13
+ inherits(CmmnLayouter, BaseLayouter);
14
+
15
+ module.exports = CmmnLayouter;
16
+
17
+
18
+ CmmnLayouter.prototype.layoutConnection = function(connection, hints) {
19
+
20
+ hints = hints || {};
21
+
22
+ var source = hints.source || connection.source,
23
+ target = hints.target || connection.target,
24
+ waypoints = connection.waypoints,
25
+ start = hints.connectionStart,
26
+ end = hints.connectionEnd;
27
+
28
+
29
+ if (!start) {
30
+ start = getConnectionDocking(waypoints && waypoints[0], source);
31
+ }
32
+
33
+ if (!end) {
34
+ end = getConnectionDocking(waypoints && waypoints[waypoints.length - 1], target);
35
+ }
36
+
37
+ var updatedWaypoints =
38
+ ManhattanLayout.repairConnection(
39
+ source, target,
40
+ start, end,
41
+ waypoints,
42
+ hints);
43
+
44
+ return updatedWaypoints || [ start, end ];
45
+ };
46
+
47
+ function getConnectionDocking(point, shape) {
48
+ return point ? (point.original || point) : getMid(shape);
49
+ }
@@ -0,0 +1,511 @@
1
+ 'use strict';
2
+
3
+ var assign = require('min-dash').assign,
4
+ inherits = require('inherits');
5
+
6
+ var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor').default;
7
+
8
+ var Collections = require('diagram-js/lib/util/Collections');
9
+
10
+ var getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
11
+ is = require('../../util/ModelUtil').is,
12
+ isCasePlanModel = require('../../util/ModelUtil').isCasePlanModel;
13
+
14
+ var getParent = require('./util/ModelingUtil').getParent,
15
+ isLabel = require('./util/ModelingUtil').isLabel;
16
+
17
+ var isAny = require('./util/ModelingUtil').isAny;
18
+
19
+ /**
20
+ * A handler responsible for updating the underlying CMMN 1.1 XML + DI
21
+ * once changes on the diagram happen
22
+ */
23
+ function CmmnUpdater(eventBus, cmmnFactory, itemRegistry, connectionDocking) {
24
+
25
+ CommandInterceptor.call(this, eventBus);
26
+
27
+ this._cmmnFactory = cmmnFactory;
28
+ this._itemRegistry = itemRegistry;
29
+
30
+ var self = this;
31
+
32
+
33
+ // connection cropping /////////////////
34
+
35
+ // crop connection ends during create/update
36
+ function cropConnection(e) {
37
+ var context = e.context,
38
+ connection;
39
+
40
+ if (!context.cropped) {
41
+ connection = context.connection;
42
+ connection.waypoints = connectionDocking.getCroppedWaypoints(connection);
43
+ context.cropped = true;
44
+ }
45
+ }
46
+
47
+ this.executed([
48
+ 'connection.layout',
49
+ 'connection.create',
50
+ 'connection.reconnectEnd',
51
+ 'connection.reconnectStart'
52
+ ], cropConnection);
53
+
54
+ this.reverted([
55
+ 'connection.layout',
56
+ 'connection.create',
57
+ 'connection.reconnectEnd',
58
+ 'connection.reconnectStart'
59
+ ], function(e) {
60
+ delete e.context.cropped;
61
+ });
62
+
63
+ // CMMN + DI update /////////////////
64
+
65
+ function updateParent(e) {
66
+ var context = e.context;
67
+
68
+ self.updateParent(context.shape || context.connection, context.oldParent);
69
+ }
70
+
71
+ function reverseUpdateParent(e) {
72
+
73
+ var context = e.context;
74
+
75
+ var element = context.shape || context.connection,
76
+ // oldParent is the (old) new parent, because we are undoing
77
+ oldParent = context.parent || context.newParent;
78
+
79
+ self.updateParent(element, oldParent);
80
+ }
81
+
82
+ this.executed([
83
+ 'shape.create',
84
+ 'shape.move',
85
+ 'shape.delete',
86
+ 'connection.delete',
87
+ 'connection.create'
88
+ ], ifCmmn(updateParent));
89
+ this.reverted([
90
+ 'shape.create',
91
+ 'shape.move',
92
+ 'shape.delete',
93
+ 'connection.delete',
94
+ 'connection.create'
95
+ ], ifCmmn(reverseUpdateParent));
96
+
97
+
98
+ // update bounds
99
+ function updateBounds(e) {
100
+ var shape = e.context.shape;
101
+ self.updateBounds(shape);
102
+ }
103
+
104
+ this.executed([
105
+ 'shape.create',
106
+ 'shape.move',
107
+ 'shape.resize'
108
+ ], ifCmmn(function(event) {
109
+
110
+ // exclude labels because they're handled separately during shape.changed
111
+ if (event.context.shape.type === 'label') {
112
+ return;
113
+ }
114
+
115
+ updateBounds(event);
116
+ }));
117
+
118
+ this.reverted([
119
+ 'shape.create',
120
+ 'shape.move',
121
+ 'shape.resize'
122
+ ], ifCmmn(function(event) {
123
+
124
+ // exclude labels because they're handled separately during shape.changed
125
+ if (event.context.shape.type === 'label') {
126
+ return;
127
+ }
128
+
129
+ updateBounds(event);
130
+ }));
131
+
132
+ // Handle labels separately. This is necessary, because the label bounds have to be updated
133
+ // every time its shape changes, not only on move, create and resize.
134
+ eventBus.on('shape.changed', function(event) {
135
+ if (event.element.type === 'label') {
136
+ updateBounds({ context: { shape: event.element } });
137
+ }
138
+ });
139
+
140
+ // attach / detach connection
141
+ function updateConnection(e) {
142
+ self.updateConnection(e.context);
143
+ }
144
+
145
+ this.executed([
146
+ 'connection.create',
147
+ 'connection.move',
148
+ 'connection.delete',
149
+ 'connection.reconnectEnd',
150
+ 'connection.reconnectStart'
151
+ ], ifCmmn(updateConnection));
152
+
153
+ this.reverted([
154
+ 'connection.create',
155
+ 'connection.move',
156
+ 'connection.delete',
157
+ 'connection.reconnectEnd',
158
+ 'connection.reconnectStart'
159
+ ], ifCmmn(updateConnection));
160
+
161
+
162
+ // update waypoints
163
+ function updateConnectionWaypoints(e) {
164
+ self.updateConnectionWaypoints(e.context.connection);
165
+ }
166
+
167
+ this.executed([
168
+ 'connection.create',
169
+ 'connection.layout',
170
+ 'connection.move',
171
+ 'connection.reconnectStart',
172
+ 'connection.reconnectEnd',
173
+ 'connection.updateWaypoints'
174
+ ], ifCmmn(updateConnectionWaypoints));
175
+
176
+ this.reverted([
177
+ 'connection.create',
178
+ 'connection.layout',
179
+ 'connection.move',
180
+ 'connection.reconnectStart',
181
+ 'connection.reconnectEnd',
182
+ 'connection.updateWaypoints'
183
+ ], ifCmmn(updateConnectionWaypoints));
184
+
185
+ // update attachments
186
+ function updateAttachment(e) {
187
+ self.updateAttachment(e.context);
188
+ }
189
+
190
+ this.executed([ 'element.updateAttachment' ], ifCmmn(updateAttachment));
191
+ this.reverted([ 'element.updateAttachment' ], ifCmmn(updateAttachment));
192
+
193
+
194
+ // update item registry
195
+
196
+ function addItem(e) {
197
+ var context = e.context,
198
+ shape = context.shape,
199
+ bo = getBusinessObject(shape);
200
+
201
+ itemRegistry.add(bo);
202
+ }
203
+
204
+ function removeItem(e) {
205
+
206
+ var context = e.context,
207
+ shape = context.shape;
208
+
209
+ if (isLabel(shape)) {
210
+ return;
211
+ }
212
+
213
+ var bo = getBusinessObject(shape);
214
+ itemRegistry.remove(bo);
215
+ }
216
+
217
+ this.executed('shape.create', ifCmmn(addItem));
218
+ this.reverted('shape.create', ifCmmn(removeItem));
219
+
220
+ this.executed('shape.delete', ifCmmn(removeItem));
221
+ this.reverted('shape.delete', ifCmmn(addItem));
222
+
223
+ }
224
+
225
+ inherits(CmmnUpdater, CommandInterceptor);
226
+
227
+ module.exports = CmmnUpdater;
228
+
229
+ CmmnUpdater.$inject = [ 'eventBus', 'cmmnFactory', 'itemRegistry', 'connectionDocking' ];
230
+
231
+
232
+ // implementation /////////////////
233
+
234
+
235
+ CmmnUpdater.prototype.updateAttachment = function(context) {
236
+ var shape = context.shape,
237
+ businessObject = getBusinessObject(shape),
238
+ host = shape.host,
239
+ businessObjectHost = host && getBusinessObject(host);
240
+
241
+ this.updateSemanticParent(businessObject, businessObjectHost);
242
+ };
243
+
244
+
245
+ CmmnUpdater.prototype.updateParent = function(element, oldParent) {
246
+ // do not update CMMN 1.1 label parent
247
+ if (isLabel(element)) {
248
+ return;
249
+ }
250
+
251
+ var businessObject = getBusinessObject(element),
252
+ parentBusinessObject = getBusinessObject(element.parent),
253
+ businessObjectDi = businessObject.di || businessObject,
254
+ parentDi = parentBusinessObject && parentBusinessObject.di;
255
+
256
+ if (isAssociation(businessObject)) {
257
+ businessObject = businessObject.cmmnElementRef;
258
+ }
259
+
260
+ if (shouldUpdateSemanticParent(businessObject)) {
261
+ this.updateSemanticParent(businessObject, parentBusinessObject);
262
+ }
263
+
264
+ if (is(parentBusinessObject, 'cmmndi:CMMNDiagram')) {
265
+ parentDi = parentBusinessObject;
266
+ }
267
+
268
+ this.updateDiParent(businessObjectDi, parentDi);
269
+ };
270
+
271
+
272
+ /**
273
+ * Update the semantic parent
274
+ *
275
+ * - add/remove the business object to/from the parent's containment(s)
276
+ * - set/unset the $parent property of the business object
277
+ *
278
+ * @param {ModdleElement} businessObject
279
+ * @param {ModdleElement} newParent
280
+ */
281
+ CmmnUpdater.prototype.updateSemanticParent = function(businessObject, newParent) {
282
+
283
+ var containment;
284
+
285
+ if (businessObject.$parent === newParent) {
286
+ return;
287
+ }
288
+
289
+ if (is(businessObject, 'cmmn:PlanItem')) {
290
+ containment = 'planItems';
291
+
292
+ if (newParent && !isCasePlanModel(newParent)) {
293
+ newParent = newParent.definitionRef;
294
+ }
295
+
296
+ } else
297
+
298
+ if (isCasePlanModel(businessObject)) {
299
+ containment = 'cases';
300
+ businessObject = businessObject.$parent;
301
+ newParent = newParent && getDefinitions(newParent);
302
+ } else
303
+
304
+ if (is(businessObject, 'cmmn:EntryCriterion')) {
305
+
306
+ if (isCasePlanModel(newParent)) {
307
+ newParent = null;
308
+ }
309
+
310
+ containment = 'entryCriteria';
311
+ } else
312
+
313
+ if (is(businessObject, 'cmmn:ExitCriterion')) {
314
+ containment = 'exitCriteria';
315
+ } else
316
+
317
+ if (is(businessObject, 'cmmn:Artifact')) {
318
+ newParent = newParent && getDefinitions(newParent);
319
+ containment = 'artifacts';
320
+ }
321
+
322
+ if (!containment) {
323
+ throw new Error('no parent for ', businessObject, newParent);
324
+ }
325
+
326
+ var children;
327
+
328
+ if (businessObject.$parent) {
329
+ // remove from old parent
330
+ children = businessObject.$parent.get(containment);
331
+ Collections.remove(children, businessObject);
332
+ }
333
+
334
+ if (newParent) {
335
+ // add to new parent
336
+ children = newParent.get(containment);
337
+ children.push(businessObject);
338
+ businessObject.$parent = newParent;
339
+ } else {
340
+ businessObject.$parent = null;
341
+ }
342
+
343
+ };
344
+
345
+
346
+ /**
347
+ * Upate the parent of an DI element
348
+ *
349
+ * - Add/remove DI element to the root element's diagramElements conainment
350
+ * - Set/unset the $parent property of the DI element
351
+ *
352
+ * @param {ModdleElement} di
353
+ * @param {ModdleElement} parentDi
354
+ */
355
+ CmmnUpdater.prototype.updateDiParent = function(di, parentDi) {
356
+ if (parentDi && !is(parentDi, 'cmmndi:CMMNDiagram')) {
357
+ parentDi = parentDi.$parent;
358
+ }
359
+
360
+ if (di.$parent === parentDi) {
361
+ return;
362
+ }
363
+
364
+ var diagramElements = (parentDi || di.$parent).get('diagramElements');
365
+
366
+ if (parentDi) {
367
+ diagramElements.push(di);
368
+ di.$parent = parentDi;
369
+ }
370
+ else {
371
+ Collections.remove(diagramElements, di);
372
+ di.$parent = null;
373
+ }
374
+ };
375
+
376
+
377
+ CmmnUpdater.prototype.updateBounds = function(shape) {
378
+ var di = shape.businessObject.di || shape.businessObject;
379
+
380
+ var bounds = isLabel(shape) ? this._getLabel(di).bounds : di.bounds;
381
+
382
+ assign(bounds, {
383
+ x: shape.x,
384
+ y: shape.y,
385
+ width: shape.width,
386
+ height: shape.height
387
+ });
388
+ };
389
+
390
+
391
+ CmmnUpdater.prototype.updateConnectionWaypoints = function(connection) {
392
+ var di = connection.businessObject;
393
+ di.set('waypoint', this._cmmnFactory.createDiWaypoints(connection.waypoints));
394
+ };
395
+
396
+
397
+ CmmnUpdater.prototype.updateConnection = function(context) {
398
+
399
+ var connection = context.connection,
400
+ businessObject = getBusinessObject(connection),
401
+ newSource = getBusinessObject(connection.source),
402
+ newTarget = getBusinessObject(connection.target),
403
+ cmmnElement = businessObject.cmmnElementRef,
404
+ sourceElem,
405
+ targetElem,
406
+ sourceAttr,
407
+ targetAttr;
408
+
409
+
410
+ if (is(cmmnElement, 'cmmn:Association')) {
411
+ sourceElem = cmmnElement;
412
+ targetElem = cmmnElement;
413
+
414
+ sourceAttr = 'sourceRef';
415
+ targetAttr = 'targetRef';
416
+ }
417
+ else {
418
+ targetElem = businessObject;
419
+ targetAttr = 'targetCMMNElementRef';
420
+
421
+ if (is(cmmnElement, 'cmmn:OnPart')) {
422
+
423
+ sourceElem = cmmnElement;
424
+ sourceAttr = 'sourceRef';
425
+
426
+ var newExitCriterionRef;
427
+ if (is(newSource, 'cmmn:ExitCriterion')) {
428
+ newExitCriterionRef = newSource;
429
+ newSource = getParent(newExitCriterionRef);
430
+ }
431
+
432
+ if (cmmnElement.exitCriterionRef !== newExitCriterionRef) {
433
+ cmmnElement.exitCriterionRef = newExitCriterionRef;
434
+ }
435
+
436
+ }
437
+ else {
438
+ sourceElem = businessObject;
439
+ sourceAttr = 'sourceCMMNElementRef';
440
+ }
441
+
442
+ }
443
+
444
+ if (sourceAttr && sourceElem[sourceAttr] !== newSource) {
445
+ sourceElem[sourceAttr] = newSource;
446
+ }
447
+
448
+ if (targetAttr && targetElem[targetAttr] !== newTarget) {
449
+ targetElem[targetAttr] = newTarget;
450
+ }
451
+
452
+ this.updateConnectionWaypoints(connection);
453
+ };
454
+
455
+ // helpers /////////////////
456
+
457
+ CmmnUpdater.prototype._getLabel = function(di) {
458
+
459
+ if (!di.label) {
460
+ di.label = this._cmmnFactory.createDiLabel();
461
+ }
462
+
463
+ if (!di.label.bounds) {
464
+ di.label.bounds = this._cmmnFactory.createDiBounds();
465
+ }
466
+
467
+ return di.label;
468
+ };
469
+
470
+
471
+ /**
472
+ * Make sure the event listener is only called
473
+ * if the touched element is a CMMN element.
474
+ *
475
+ * @param {Function} fn
476
+ * @return {Function} guarded function
477
+ */
478
+ function ifCmmn(fn) {
479
+
480
+ return function(event) {
481
+
482
+ var context = event.context,
483
+ element = context.shape || context.connection;
484
+
485
+ if (is(element, 'cmmn:CMMNElement') || is(element, 'cmmndi:CMMNDiagramElement')) {
486
+ fn(event);
487
+ }
488
+ };
489
+ }
490
+
491
+ /**
492
+ * Returns the cmmn:Definitions element for a given element.
493
+ */
494
+ function getDefinitions(element) {
495
+ return getParent(element, 'cmmn:Definitions');
496
+ }
497
+
498
+ function shouldUpdateSemanticParent(element) {
499
+ return !isAny(element, [
500
+ 'cmmn:CaseFileItem',
501
+ 'cmmn:Criterion',
502
+ 'cmmn:DiscretionaryItem',
503
+ 'cmmn:OnPart',
504
+ 'cmmndi:CMMNEdge'
505
+ ]);
506
+ }
507
+
508
+ function isAssociation(connection) {
509
+ connection = connection.businessObject || connection;
510
+ return !!(connection.cmmnElementRef && is(connection.cmmnElementRef, 'cmmn:Association'));
511
+ }