@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,620 @@
1
+ 'use strict';
2
+
3
+ var inherits = require('inherits');
4
+
5
+ var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor').default;
6
+
7
+ var some = require('min-dash').some,
8
+ forEach = require('min-dash').forEach;
9
+
10
+ var ModelUtil = require('../../../util/ModelUtil'),
11
+ is = ModelUtil.is,
12
+ isCasePlanModel = ModelUtil.isCasePlanModel,
13
+ getDefinition = ModelUtil.getDefinition,
14
+ getBusinessObject = ModelUtil.getBusinessObject;
15
+
16
+ var getParent = require('../util/ModelingUtil').getParent,
17
+ isLabel = require('../util/ModelingUtil').isLabel,
18
+ getParents = require('../util/ModelingUtil').getParents;
19
+
20
+ var PlanItemDefinitionUtil = require('../util/PlanItemDefinitionUtil'),
21
+ isDiscretionaryToHumanTask = PlanItemDefinitionUtil.isDiscretionaryToHumanTask,
22
+ isDiscretionaryItem = PlanItemDefinitionUtil.isDiscretionaryItem,
23
+ isPlanFragment = PlanItemDefinitionUtil.isPlanFragment,
24
+ getAllDiscretionaryItems = PlanItemDefinitionUtil.getAllDiscretionaryItems,
25
+ isHumanTask = PlanItemDefinitionUtil.isHumanTask;
26
+
27
+
28
+ /**
29
+ * A handler responsible for adding, moving and deleting discretionary items
30
+ * and adding them to planning table. These changes are reflected to
31
+ * the underlying CMMN 1.1 XML.
32
+ */
33
+ function PlanningTableUpdater(eventBus, cmmnFactory, modeling, itemRegistry) {
34
+
35
+ this._cmmnFactory = cmmnFactory;
36
+ this._modeling = modeling;
37
+ this._itemRegistry = itemRegistry;
38
+
39
+ var self = this;
40
+
41
+ CommandInterceptor.call(this, eventBus);
42
+
43
+ var containment = 'tableItems';
44
+
45
+ // CONNECTION /////////////////////////////////////////////
46
+
47
+
48
+ // delete + reconnectEnd //////////////////////////////////
49
+
50
+
51
+ this.preExecuted([ 'connection.delete', 'connection.reconnectEnd', 'connection.reconnectStart' ], function(event) {
52
+
53
+ var context = event.context,
54
+ isReconnectStart = (event.command === 'connection.reconnectStart'),
55
+ connection = context.connection,
56
+ target = connection.target;
57
+
58
+ if (!isDiscretionaryConnection(connection)) {
59
+ return;
60
+ }
61
+
62
+ if (isReconnectStart) {
63
+
64
+ if (context.newSource && context.newTarget) {
65
+ target = context.newSource;
66
+ context.oldPlanningTable = getParentPlanningTable(target);
67
+ }
68
+ else {
69
+ return;
70
+ }
71
+
72
+ }
73
+
74
+ // (1) remember current
75
+ context.planningTable = getParentPlanningTable(target);
76
+
77
+ // (2) if the target did not change, then do nothing (in case of reconnectEnd)
78
+ if (target === context.newTarget) {
79
+ return;
80
+ }
81
+
82
+ // (3) is there at least another discretionary connection referencing
83
+ // this target.
84
+ // note: there could be multiple plan items (with the same definition -
85
+ // human task) referencing the same discretionary item. in such case
86
+ // the deletion/reconnection of a discretionary connection does not trigger
87
+ // the deletion of the other discretionary connections. As a result, the
88
+ // the discretionary item remains in its current planning table.
89
+ if (isReferencedByAnotherDiscretionaryConnection(target, connection)) {
90
+ return;
91
+ }
92
+
93
+ // (4) get new target definition of discretionary item
94
+ var definition = getTargetDefinition(target.parent);
95
+
96
+ // (5) create a planning table if necessary
97
+ var planningTable = self.createPlanningTable(definition);
98
+
99
+ // (6) move (current target) discretionary item from current planning table
100
+ // to the new planning table
101
+ modeling.updateSemanticParent(target, planningTable, containment);
102
+
103
+ });
104
+
105
+
106
+ this.postExecuted('connection.delete', function(context) {
107
+
108
+ if (!isDiscretionaryConnection(context.connection)) {
109
+ return;
110
+ }
111
+
112
+ // triggers deletion of planning table if it is empty
113
+ self.deletePlanningTable(context.planningTable);
114
+
115
+ }, true);
116
+
117
+
118
+ this.postExecuted('connection.reconnectEnd', function(context) {
119
+
120
+ var connection = context.connection,
121
+ target = connection.target;
122
+
123
+ if (!isDiscretionaryConnection(connection)) {
124
+ return;
125
+ }
126
+
127
+ // (1) remember old planning table of new target
128
+ var oldPlanningTable = getParentPlanningTable(target);
129
+
130
+ // (2) add new target as discretionary item into the planning table of the source element
131
+ modeling.updateSemanticParent(target, context.planningTable, containment);
132
+
133
+ // (3) remove old planning table if its empty
134
+ self.deletePlanningTable(oldPlanningTable);
135
+
136
+ }, true);
137
+
138
+
139
+ this.postExecuted('connection.reconnectStart', function(context) {
140
+
141
+ var connection = context.connection;
142
+
143
+ if (!isDiscretionaryConnection(connection)) {
144
+ return;
145
+ }
146
+
147
+ if (!context.newSource || !context.newTarget) {
148
+ return;
149
+ }
150
+
151
+ self.deletePlanningTable(context.oldPlanningTable);
152
+
153
+ }, true);
154
+
155
+ // create + reconnectStart ////////////////////////////////////////
156
+
157
+ this.preExecuted([ 'connection.create', 'connection.reconnectStart' ], function(context) {
158
+
159
+ var connection = context.connection,
160
+ source = context.newSource || context.source,
161
+ target = context.target || context.newTarget || connection.target;
162
+
163
+ if (!isDiscretionaryConnection(connection)) {
164
+ return;
165
+ }
166
+
167
+ // (1) remember planning table of target discretionary item
168
+ context.planningTable = getParentPlanningTable(target);
169
+
170
+ var definition = getDefinition(source);
171
+
172
+ if (connection.source) {
173
+ var oldDefinition = getDefinition(connection.source);
174
+ if (oldDefinition === definition) {
175
+ return;
176
+ }
177
+ }
178
+
179
+ // (2) create a planning table if necessary
180
+ var planningTable = self.createPlanningTable(definition);
181
+
182
+ // (3) add target discretionary item to planning table
183
+ modeling.updateSemanticParent(target, planningTable, containment);
184
+
185
+ }, true);
186
+
187
+
188
+ this.postExecuted([ 'connection.create', 'connection.reconnectStart' ], function(context) {
189
+
190
+ var connection = context.connection;
191
+ if (!isDiscretionaryConnection(connection)) {
192
+ return;
193
+ }
194
+
195
+ // remove planning table if its empty
196
+ self.deletePlanningTable(context.planningTable);
197
+
198
+ }, true);
199
+
200
+
201
+ // SHAPE /////////////////////////////////////////////////////////////////////////////
202
+
203
+ this.preExecuted('elements.move', 500, function(context) {
204
+
205
+ var allShapes = context.closure.allShapes,
206
+ newParent = context.newParent,
207
+ hints = context.hints,
208
+ oldParent = hints && hints.primaryShape && hints.primaryShape.parent,
209
+ replacements = context.definitionReplacements,
210
+ replacedPlanningTableArray = [],
211
+ planningTableReplacedBy = {};
212
+
213
+
214
+ function clonePlanningTable(planningTable) {
215
+ var newPlanningTable = cmmnFactory.create('cmmn:PlanningTable', {
216
+ applicabilityRules: planningTable.applicabilityRules
217
+ });
218
+ var idx = replacedPlanningTableArray.push(planningTable);
219
+ planningTableReplacedBy[idx-1] = newPlanningTable;
220
+
221
+ return newPlanningTable;
222
+ }
223
+
224
+
225
+ if (!newParent || oldParent === newParent) {
226
+ return;
227
+ }
228
+
229
+
230
+ forEach(allShapes, function(shape) {
231
+
232
+ var bo = getBusinessObject(shape),
233
+ newPlanningTables = [],
234
+ discretionaryTo,
235
+ replacedBy,
236
+ items,
237
+ planningTables,
238
+ previousPlanningTable;
239
+
240
+
241
+ if (!isDiscretionaryItem(shape) || isLabel(shape)) {
242
+ return;
243
+ }
244
+
245
+ discretionaryTo = getParent(bo, 'cmmn:PlanItemDefinition');
246
+ if (!is(discretionaryTo, 'cmmn:HumanTask')) {
247
+ return;
248
+ }
249
+
250
+ replacedBy = replacements[discretionaryTo.id];
251
+ if (!replacedBy) {
252
+ return;
253
+ }
254
+
255
+ // discretionary item is already contained by replacement
256
+ if ((getAllDiscretionaryItems(replacedBy) || []).indexOf(bo) !== -1) {
257
+ return;
258
+ }
259
+
260
+ // have been all contained discretionary items moved?
261
+ items = getAllDiscretionaryItems(discretionaryTo);
262
+ var allMoved = !some(items, function(item) {
263
+ return !allShapes[item.id];
264
+ });
265
+
266
+
267
+ if (allMoved) {
268
+
269
+ // if yes, then just move planning table to replacement
270
+
271
+ var planningTable = discretionaryTo.planningTable;
272
+
273
+ modeling.updateProperties(replacedBy, {
274
+ planningTable: planningTable
275
+ }, itemRegistry.getShapes(replacedBy));
276
+
277
+ modeling.updateSemanticParent(planningTable, replacedBy);
278
+
279
+ modeling.updateProperties(discretionaryTo, {
280
+ planningTable: undefined
281
+ }, itemRegistry.getShapes(discretionaryTo));
282
+
283
+ return;
284
+ }
285
+
286
+
287
+ planningTables = getParents(bo, 'cmmn:PlanningTable');
288
+
289
+ if (planningTables && planningTables.length) {
290
+
291
+ forEach(planningTables, function(planningTable) {
292
+
293
+ var idx = replacedPlanningTableArray.indexOf(planningTable),
294
+ newPlanningTable;
295
+
296
+ if (idx === -1) {
297
+ newPlanningTable = clonePlanningTable(planningTable);
298
+ }
299
+ else {
300
+ newPlanningTable = planningTableReplacedBy[idx];
301
+ }
302
+
303
+ if (previousPlanningTable && !previousPlanningTable.$parent) {
304
+ modeling.updateSemanticParent(previousPlanningTable, newPlanningTable, 'tableItems');
305
+ }
306
+
307
+ previousPlanningTable = newPlanningTable;
308
+ newPlanningTables.push(newPlanningTable);
309
+
310
+ });
311
+
312
+ if (!replacedBy.planningTable) {
313
+
314
+ modeling.updateProperties(replacedBy, {
315
+ planningTable: previousPlanningTable
316
+ }, itemRegistry.getShapes(replacedBy));
317
+ modeling.updateSemanticParent(previousPlanningTable, replacedBy);
318
+
319
+ }
320
+
321
+ var first = newPlanningTables.splice(0, 1)[0],
322
+ oldPlanningTable = getParentPlanningTable(bo);
323
+
324
+ modeling.updateSemanticParent(bo, first, 'tableItems');
325
+
326
+ self.deletePlanningTable(oldPlanningTable);
327
+ }
328
+
329
+ });
330
+
331
+ }, true);
332
+
333
+
334
+ this.preExecuted([ 'shape.create', 'shape.move' ], function(context) {
335
+
336
+ var shape = context.shape;
337
+
338
+ if (!isDiscretionaryItem(shape) || isLabel(shape)) {
339
+ return;
340
+ }
341
+
342
+ // (1) if is discretionary to human task, then there is nothing to do
343
+ // in case of 'shape.move'
344
+ if (isDiscretionaryToHumanTask(shape)) {
345
+ return;
346
+ }
347
+
348
+ // remember old planning table
349
+ context.planningTable = getParentPlanningTable(shape);
350
+
351
+ var newParent = context.parent || context.newParent;
352
+
353
+ if (newParent) {
354
+
355
+ // (2) parent changed
356
+
357
+ var definition = getTargetDefinition(newParent);
358
+
359
+ // (3) create new planning table if necessary
360
+ var planningTable = self.createPlanningTable(definition);
361
+
362
+ // (4) add discretionary item to planning table
363
+ modeling.updateSemanticParent(shape, planningTable, containment);
364
+ }
365
+
366
+ }, true);
367
+
368
+
369
+ this.postExecuted('shape.move', function(context) {
370
+
371
+ var shape = context.shape;
372
+
373
+ if (!isDiscretionaryItem(shape) || isLabel(shape)) {
374
+ return;
375
+ }
376
+
377
+ // if an item which is discretionary to a human task is moved,
378
+ // then no update is necessary
379
+ if (isDiscretionaryToHumanTask(shape)) {
380
+ return;
381
+ }
382
+
383
+ self.deletePlanningTable(context.planningTable);
384
+
385
+ }, true);
386
+
387
+
388
+ this.preExecuted('shape.delete', function(context) {
389
+
390
+ var shape = context.shape;
391
+
392
+ if (!isDiscretionaryItem(shape) || isLabel(shape)) {
393
+ return;
394
+ }
395
+
396
+ // remember old planning table
397
+ context.planningTable = getParentPlanningTable(shape);
398
+
399
+ // remove discretionary item from planning table
400
+ modeling.updateSemanticParent(shape, null, containment);
401
+
402
+ }, true);
403
+
404
+
405
+ this.postExecuted('shape.delete', function(context) {
406
+
407
+ var shape = context.shape;
408
+
409
+ if (!isDiscretionaryItem(shape) || isLabel(shape)) {
410
+ return;
411
+ }
412
+
413
+ self.deletePlanningTable(context.planningTable);
414
+
415
+ }, true);
416
+
417
+
418
+ this.postExecuted('shape.delete', 500, function(context) {
419
+
420
+ var shape = context.shape;
421
+
422
+ var definition = getDefinition(shape);
423
+
424
+ if (!isHumanTask(definition) || definition.$parent) {
425
+ return;
426
+ }
427
+
428
+ var discretionaryItems = getAllDiscretionaryItems(definition);
429
+
430
+ // repair the model
431
+ forEach(discretionaryItems, function(item) {
432
+ var shapeItem = itemRegistry.getShape(item.id);
433
+
434
+ if (shapeItem) {
435
+ // get new target definition of discretionary item
436
+ var definition = getTargetDefinition(shapeItem.parent);
437
+
438
+ // create a planning table if necessary
439
+ var planningTable = self.createPlanningTable(definition);
440
+
441
+ // move (current target) discretionary item from current planning table
442
+ // to the new planning table
443
+ modeling.updateSemanticParent(shapeItem, planningTable, containment);
444
+ }
445
+
446
+ });
447
+
448
+ if (definition.planningTable) {
449
+ self.deletePlanningTable(definition.planningTable);
450
+ }
451
+
452
+ }, true);
453
+
454
+ // API ////////////////////////////////////////////////////////
455
+
456
+ /**
457
+ * Creates a new planning table for the given definition, if necessary.
458
+ *
459
+ * If the given definition already contains a planning table, this
460
+ * planning table is returned.
461
+ *
462
+ * @param {ModdleElement} definition where the planning table is added
463
+ *
464
+ * @return {ModdleElement} the create planning table
465
+ */
466
+ this.createPlanningTable = function(definition) {
467
+
468
+ var planningTable = definition.planningTable;
469
+
470
+ if (!planningTable) {
471
+
472
+ // (1) create new planning table
473
+ planningTable = self._cmmnFactory.create('cmmn:PlanningTable');
474
+
475
+ // (2) filter all items which are affected by adding a planning
476
+ // table to its definition
477
+ var shapes = itemRegistry.getShapes(definition);
478
+
479
+ // (3) set planning table
480
+ modeling.updateProperties(definition, {
481
+ planningTable: planningTable
482
+ }, shapes);
483
+
484
+ // (4) set parent of planning table to definition
485
+ modeling.updateSemanticParent(planningTable, definition);
486
+ }
487
+
488
+
489
+ return planningTable;
490
+ };
491
+
492
+
493
+ /**
494
+ * Deletes a given planning table from the definition. If the planning
495
+ * table is nested inside other planning tables, then the plannings tables
496
+ * are also deleted, if they do not contain any element.
497
+ *
498
+ * @param {ModdleElement} planningTable to delete
499
+ *
500
+ */
501
+ this.deletePlanningTable = function(planningTable) {
502
+
503
+ // According to spec: a planning table must contain at least one element.
504
+ // if it does not contain any element, then the planning table is deleted.
505
+
506
+ // (1) cannot delete planning table if contains at least one element
507
+ if (planningTable.get(containment).length > 0) {
508
+ return;
509
+ }
510
+
511
+ // (2) if planning table does not contain any element, then remove it
512
+ var oldParent = planningTable.$parent;
513
+ while (is(oldParent, 'cmmn:PlanningTable') && !planningTable.get(containment).length) {
514
+ modeling.updateSemanticParent(planningTable, null, containment);
515
+ planningTable = oldParent;
516
+ oldParent = oldParent.$parent;
517
+ }
518
+
519
+ if (is(oldParent, 'cmmn:PlanItemDefinition')) {
520
+
521
+ if (planningTable && !planningTable.get(containment).length) {
522
+
523
+ // (3) get definition containing this planning table
524
+ var definition = getParent(planningTable, 'cmmn:PlanItemDefinition');
525
+
526
+ // (4) filter all items which are affected by removing this planning
527
+ // table from its definition
528
+ var shapes = itemRegistry.getShapes(definition);
529
+
530
+ // (5) set planning table attribute to undefined
531
+ modeling.updateProperties(definition, {
532
+ planningTable: undefined
533
+ }, shapes);
534
+
535
+ // (6) set planning tables parent to null
536
+ modeling.updateSemanticParent(planningTable, null, null);
537
+ }
538
+ }
539
+ };
540
+
541
+
542
+ /**
543
+ * Returns true, if there is another incoming discretionary connection
544
+ * apart the given connection.
545
+ *
546
+ * @param {djs.mode.Base} shape
547
+ * @param {djs.mode.Base} connection
548
+ *
549
+ * @return {boolean} if there is another incoming discretionary connection
550
+ */
551
+ function isReferencedByAnotherDiscretionaryConnection(shape, connection) {
552
+ return some(shape.incoming, function(con) {
553
+ return con !== connection && isDiscretionaryConnection(con);
554
+ });
555
+ }
556
+
557
+
558
+ function isDiscretionaryConnection(connection) {
559
+ return !connection.businessObject.cmmnElementRef;
560
+ }
561
+
562
+ }
563
+
564
+ PlanningTableUpdater.$inject = [
565
+ 'eventBus',
566
+ 'cmmnFactory',
567
+ 'modeling',
568
+ 'itemRegistry'
569
+ ];
570
+
571
+ inherits(PlanningTableUpdater, CommandInterceptor);
572
+
573
+ module.exports = PlanningTableUpdater;
574
+
575
+
576
+ function getTargetDefinition(shape) {
577
+ var target = fixTarget(shape);
578
+ return getDefinition(target) || getBusinessObject(target);
579
+ }
580
+
581
+ /**
582
+ * Fixes the target.
583
+ * A discretionary item cannot be added to plan fragment,
584
+ * in that case the discretionary item is added to the visual
585
+ * surrounding stage.
586
+ *
587
+ * @param {djs.model.Base} target
588
+ *
589
+ * @return {djs.model.Base} the fixed target
590
+ */
591
+ function fixTarget(target) {
592
+ if (target && !isCasePlanModel(target)) {
593
+
594
+ var definition = getDefinition(target);
595
+
596
+ if (isPlanFragment(definition)) {
597
+ target = getParent(target, [
598
+ 'cmmn:Stage',
599
+ 'cmmn:PlanItem',
600
+ 'cmmn:DiscretionaryItem'
601
+ ]);
602
+ target = fixTarget(target);
603
+ }
604
+ }
605
+
606
+ return target;
607
+ }
608
+
609
+
610
+ /**
611
+ * Returns parent planning table of the given element.
612
+ *
613
+ * @param {ModdleElement} element
614
+ *
615
+ * @param {ModdleElement} the parent planning table
616
+ */
617
+ function getParentPlanningTable(element) {
618
+ element = getBusinessObject(element);
619
+ return getParent(element, 'cmmn:PlanningTable');
620
+ }