@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,1040 @@
1
+ 'use strict';
2
+
3
+ var inherits = require('inherits');
4
+
5
+ var some = require('min-dash').some,
6
+ forEach = require('min-dash').forEach,
7
+ assign = require('min-dash').assign,
8
+ filter = require('min-dash').filter;
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 isCollapsed = require('../../util/DiUtil').isCollapsed;
17
+
18
+ var ModelingUtil = require('../modeling/util/ModelingUtil'),
19
+ isAny = ModelingUtil.isAny,
20
+ isSame = ModelingUtil.isSame,
21
+ isSameCase = ModelingUtil.isSameCase,
22
+ getParent = ModelingUtil.getParent,
23
+ getParents = ModelingUtil.getParents;
24
+
25
+ var PlanItemDefinitionUtil = require('../modeling/util/PlanItemDefinitionUtil'),
26
+ isDiscretionaryToHumanTask = PlanItemDefinitionUtil.isDiscretionaryToHumanTask,
27
+ isHumanTask = PlanItemDefinitionUtil.isHumanTask,
28
+ isDiscretionaryItem = PlanItemDefinitionUtil.isDiscretionaryItem;
29
+
30
+ var isCriterionAttachment = require('../snapping/CmmnSnappingUtil').getCriterionAttachment;
31
+
32
+ var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider').default;
33
+
34
+
35
+ /**
36
+ * CMMN specific modeling rule
37
+ */
38
+ function CmmnRules(eventBus) {
39
+ RuleProvider.call(this, eventBus);
40
+ }
41
+
42
+ inherits(CmmnRules, RuleProvider);
43
+
44
+ CmmnRules.$inject = [ 'eventBus' ];
45
+
46
+ module.exports = CmmnRules;
47
+
48
+ CmmnRules.prototype.init = function() {
49
+
50
+ var self = this;
51
+
52
+ this.addRule('connection.start', function(context) {
53
+ var source = context.source;
54
+
55
+ return canStartConnection(source);
56
+ });
57
+
58
+ this.addRule('connection.create', function(context) {
59
+
60
+ var source = context.source,
61
+ target = context.target,
62
+ allowed = false,
63
+ hints = context.hints || {},
64
+ targetParent = hints.targetParent,
65
+ targetAttach = hints.targetAttach;
66
+
67
+ // don't allow incoming connections on
68
+ // attach from context-pad
69
+ if (targetAttach) {
70
+ return false;
71
+ }
72
+
73
+ // temporarily set target parent for scoping
74
+ // checks to work
75
+ if (targetParent) {
76
+ target.parent = targetParent;
77
+ }
78
+
79
+ try {
80
+ allowed = self.canConnect(source, target) ||
81
+ self.canReplaceConnectionEnd(source, target, 'target');
82
+
83
+ if (!allowed) {
84
+
85
+ allowed = self.canConnect(target, source) ||
86
+ self.canReplaceConnectionEnd(target, source, 'source');
87
+
88
+ if (allowed) {
89
+ assign(allowed, {
90
+ reverse: true
91
+ });
92
+ }
93
+ }
94
+ } finally {
95
+ // unset temporary target parent
96
+ if (targetParent) {
97
+ target.parent = null;
98
+ }
99
+ }
100
+
101
+ return allowed;
102
+ });
103
+
104
+ this.addRule('connection.reconnectStart', function(context) {
105
+
106
+ var connection = context.connection,
107
+ hover = context.hover,
108
+ source = hover || context.source,
109
+ target = connection.target,
110
+ allowed = false;
111
+
112
+ allowed = self.canConnect(source, target, connection);
113
+
114
+ if (!allowed && hover) {
115
+
116
+ allowed = self.canReplaceConnectionEnd(hover, target, 'source');
117
+
118
+ if (!allowed) {
119
+
120
+ allowed = self.canConnect(target, hover, connection) ||
121
+ self.canReplaceConnectionEnd(target, hover, 'target');
122
+
123
+ if (allowed) {
124
+ assign(allowed, {
125
+ reverse: true
126
+ });
127
+ }
128
+
129
+ }
130
+
131
+ }
132
+
133
+ return allowed;
134
+
135
+ });
136
+
137
+ this.addRule('connection.reconnectEnd', function(context) {
138
+
139
+ var connection = context.connection,
140
+ source = connection.source,
141
+ hover = context.hover,
142
+ target = hover || context.target,
143
+ allowed = false;
144
+
145
+ allowed = self.canConnect(source, target, connection);
146
+
147
+ if (!allowed && hover) {
148
+
149
+ allowed = self.canReplaceConnectionEnd(source, hover, 'target');
150
+
151
+ if (!allowed) {
152
+
153
+ allowed = self.canConnect(hover, source, connection) ||
154
+ self.canReplaceConnectionEnd(hover, source, 'source');
155
+
156
+ if (allowed) {
157
+ assign(allowed, {
158
+ reverse: true
159
+ });
160
+ }
161
+
162
+ }
163
+
164
+ }
165
+
166
+ return allowed;
167
+
168
+ });
169
+
170
+ this.addRule('connection.updateWaypoints', function(context) {
171
+ var connection = context.connection;
172
+
173
+ return {
174
+ type: connection.type,
175
+ businessObject: connection.businessObject
176
+ };
177
+ });
178
+
179
+ this.addRule('shape.attach', function(context) {
180
+
181
+ return self.canAttach(
182
+ context.shape,
183
+ context.target,
184
+ null,
185
+ context.position
186
+ );
187
+ });
188
+
189
+ this.addRule('shape.create', function(context) {
190
+
191
+ var target = context.target,
192
+ shape = context.shape,
193
+ source = context.source,
194
+ position = context.position,
195
+ shapes = [ shape ];
196
+
197
+ return self.canCreate(shape, target, source, position) ||
198
+ self.canReplace(shapes, target, position, source);
199
+ });
200
+
201
+ this.addRule('shape.resize', function(context) {
202
+
203
+ var shape = context.shape,
204
+ newBounds = context.newBounds;
205
+
206
+ return self.canResize(shape, newBounds);
207
+ });
208
+
209
+ this.addRule('elements.move', function(context) {
210
+ var target = context.target,
211
+ shapes = context.shapes,
212
+ position = context.position;
213
+
214
+ return self.canAttach(shapes, target, null, position) ||
215
+ self.canMove(shapes, target, position) ||
216
+ self.canReplace(shapes, target, position);
217
+ });
218
+
219
+ this.addRule('shape.replace', function(context) {
220
+
221
+ var element = context.element,
222
+ host;
223
+
224
+ if (isCriterion(element)) {
225
+
226
+ host = element.host;
227
+
228
+ if (isCasePlanModel(host)) {
229
+ return false;
230
+ }
231
+
232
+ if (isTask(host) && !isBlocking(host)) {
233
+ return false;
234
+ }
235
+
236
+ if (isMilestone(host) || isEventListener(host)) {
237
+ return false;
238
+ }
239
+
240
+ }
241
+
242
+ });
243
+
244
+ this.addRule([ 'elements.delete' ], function(context) {
245
+ return self.canRemove(context.elements);
246
+ });
247
+
248
+ };
249
+
250
+
251
+ CmmnRules.prototype.canRemove = function(elements) {
252
+
253
+ // do not allow deletion of labels
254
+ return filter(elements, function(e) {
255
+ return !isLabel(e);
256
+ });
257
+
258
+ };
259
+
260
+
261
+ CmmnRules.prototype.canMove = function(elements, target) {
262
+
263
+ var self = this;
264
+
265
+ // allow default move check to start move operation
266
+ if (!target) {
267
+ return true;
268
+ }
269
+
270
+ return elements.every(function(element) {
271
+
272
+ if (isDiscretionaryItem(element)) {
273
+ if (!self.canMoveDiscretionaryItem(element, elements, target)) {
274
+ return false;
275
+ }
276
+ }
277
+
278
+ return self.canDrop(element, target);
279
+ });
280
+
281
+ };
282
+
283
+
284
+ CmmnRules.prototype.canMoveDiscretionaryItem = function(element, elements, target) {
285
+
286
+ return !isPlanFragment(target) || some(element.incoming, function(connection) {
287
+ var source = connection.source;
288
+ if (isDiscretionaryConnection(connection)) {
289
+ return isParent(target, source) || elements.indexOf(source) !== -1;
290
+ }
291
+ });
292
+
293
+ };
294
+
295
+ CmmnRules.prototype.canCreate = function(shape, target, source, position) {
296
+
297
+ var self = this;
298
+
299
+ if (!target) {
300
+ return false;
301
+ }
302
+
303
+ if (isLabel(target)) {
304
+ return null;
305
+ }
306
+
307
+ if (isSame(source, target)) {
308
+ return false;
309
+ }
310
+
311
+ // ensure we do not drop the element
312
+ // into source
313
+ if (source && isParent(source, target)) {
314
+ return false;
315
+ }
316
+
317
+ if (isDiscretionaryItem(shape)) {
318
+ if (!self.canCreateDiscretionaryItem(shape, target, source)) {
319
+ return false;
320
+ }
321
+ }
322
+
323
+ return self.canDrop(shape, target, position);
324
+
325
+ };
326
+
327
+ CmmnRules.prototype.canCreateDiscretionaryItem = function(shape, target, source) {
328
+ return !isPlanFragment(target) || isParent(target, source);
329
+ };
330
+
331
+
332
+ CmmnRules.prototype.canDrop = function(element, target) {
333
+
334
+ // can move labels everywhere
335
+ if (isLabel(element) && !isConnection(target)) {
336
+ return true;
337
+ }
338
+
339
+ if (isArtifact(element)) {
340
+
341
+ return is(target, 'cmmndi:CMMNDiagram') ||
342
+ isPlanFragment(target, true);
343
+ }
344
+
345
+ if (isCriterion(element)) {
346
+ return false;
347
+ }
348
+
349
+ if (isCasePlanModel(element)) {
350
+ // allow casePlanModels to drop only on root (CMMNDiagram)
351
+ return is(target, 'cmmndi:CMMNDiagram');
352
+ }
353
+
354
+ // allow any other element to drop on a case plan model or on an expanded stage
355
+ if (!isPlanFragment(target, true)) {
356
+ return false;
357
+ }
358
+
359
+ return !isCollapsed(target);
360
+
361
+ };
362
+
363
+
364
+ CmmnRules.prototype.canResize = function(shape, newBounds) {
365
+ if (isPlanFragment(shape, true)) {
366
+ return (!isCollapsed(shape)) && (
367
+ !newBounds || (newBounds.width >= 100 && newBounds.height >= 80)
368
+ );
369
+ }
370
+
371
+ if (isTextAnnotation(shape)) {
372
+ return true;
373
+ }
374
+
375
+ return false;
376
+ };
377
+
378
+ CmmnRules.prototype.canConnect = function(source, target, connection) {
379
+
380
+ if (nonExistingOrLabel(source) || nonExistingOrLabel(target)) {
381
+ return null;
382
+ }
383
+
384
+ // Disallow connections with same target and source element.
385
+ if (isSame(source, target)) {
386
+ return false;
387
+ }
388
+
389
+ if (this.canConnectPlanItemOnPartConnection(source, target)) {
390
+ return {
391
+ type: 'cmmn:PlanItemOnPart',
392
+ isStandardEventVisible: true
393
+ };
394
+ }
395
+
396
+ if (this.canConnectCaseFileItemOnPartConnection(source, target)) {
397
+ return {
398
+ type: 'cmmn:CaseFileItemOnPart',
399
+ isStandardEventVisible: true
400
+ };
401
+ }
402
+
403
+ if (this.canConnectDiscretionaryConnection(source, target, connection)) {
404
+ return {
405
+ type: 'cmmndi:CMMNEdge'
406
+ };
407
+ }
408
+
409
+ if (connection &&
410
+ is(connection.businessObject.cmmnElementRef, 'cmmn:Association') &&
411
+ this.canConnectAssociation(source, target)) {
412
+
413
+ return {
414
+ type: 'cmmn:Association'
415
+ };
416
+ }
417
+
418
+ if (isTextAnnotation(source) || isTextAnnotation(target)) {
419
+
420
+ return {
421
+ type: 'cmmn:Association'
422
+ };
423
+ }
424
+
425
+ return false;
426
+ };
427
+
428
+
429
+ CmmnRules.prototype.canConnectDiscretionaryConnection = function(source, target, connection) {
430
+
431
+ if (!isHumanTask(getDefinition(source))) {
432
+ return false;
433
+ }
434
+
435
+ if (!isBlocking(source)) {
436
+ return false;
437
+ }
438
+
439
+ if (!isDiscretionaryItem(target)) {
440
+ return false;
441
+ }
442
+
443
+ // A HumanTask MUST NOT be discretionary to itself.
444
+ var sourceDefinition = getDefinition(source);
445
+ var targetDefinition = getDefinition(target);
446
+
447
+ if (isSame(sourceDefinition, targetDefinition)) {
448
+ return false;
449
+ }
450
+
451
+ var sourceParent = getParent(source);
452
+ var targetParent = getParent(target);
453
+
454
+ if (!isSame(sourceParent, targetParent)) {
455
+ return false;
456
+ }
457
+
458
+ // if the target discretionary item is already
459
+ // part of a human task, then it should not be
460
+ // possible to create a connection to it in some
461
+ // cases.
462
+ if (isDiscretionaryToHumanTask(target)) {
463
+
464
+ if (!isUniqueDiscretionaryConnection(source, target, connection)) {
465
+ return false;
466
+ }
467
+
468
+ var parent = getParent(getBusinessObject(target), 'cmmn:HumanTask');
469
+
470
+ if (!isSame(getDefinition(source), parent)) {
471
+ if (hasIncomingDiscretionaryConnections(target, connection)) {
472
+ return false;
473
+ }
474
+ }
475
+
476
+ }
477
+
478
+ return true;
479
+ };
480
+
481
+
482
+ CmmnRules.prototype.canConnectPlanItemOnPartConnection = function(source, target) {
483
+
484
+ if (!isSameCase(source, target)) {
485
+ return false;
486
+ }
487
+
488
+ if (isExitCriterion(source)) {
489
+ source = source.host;
490
+ }
491
+
492
+ if (isSame(source, target.host)) {
493
+ return false;
494
+ }
495
+
496
+ if (isParent(source, target.host)) {
497
+ return false;
498
+ }
499
+
500
+ if (isEntryCriterion(target) && isParent(target.host, source)) {
501
+ return false;
502
+ }
503
+
504
+ return isPlanItem(source) && isCriterion(target);
505
+ };
506
+
507
+
508
+ CmmnRules.prototype.canConnectCaseFileItemOnPartConnection = function(source, target) {
509
+ return !!(isSameCase(source, target) &&
510
+ isCaseFileItem(source) &&
511
+ isCriterion(target));
512
+ };
513
+
514
+ CmmnRules.prototype.canConnectAssociation = function(source, target) {
515
+
516
+ // do not connect connections
517
+ if (isConnection(source) || isConnection(target)) {
518
+ return false;
519
+ }
520
+
521
+ // connect if different parent
522
+ return !isParent(target, source) &&
523
+ !isParent(source, target);
524
+
525
+ };
526
+
527
+ CmmnRules.prototype.canAttach = function(elements, target, source, position) {
528
+
529
+ if (isSame(source, target)) {
530
+ return false;
531
+ }
532
+
533
+
534
+ if (!Array.isArray(elements)) {
535
+ elements = [ elements ];
536
+ }
537
+
538
+ // only (re-)attach one element at a time
539
+ if (elements.length !== 1) {
540
+ return false;
541
+ }
542
+
543
+ var element = elements[0];
544
+
545
+ // do not attach labels
546
+ if (isLabel(element)) {
547
+ return false;
548
+ }
549
+
550
+ // only handle entry/exit criterion
551
+ if (!isCriterion(element)) {
552
+ return false;
553
+ }
554
+
555
+ // allow default move operation
556
+ if (!target) {
557
+ return true;
558
+ }
559
+
560
+ if (!this.canAttachCriterion(element, target, position, source)) {
561
+ return false;
562
+ }
563
+
564
+ return 'attach';
565
+
566
+ };
567
+
568
+
569
+ CmmnRules.prototype.canAttachEntryCriterion = function(element, target, position, source) {
570
+
571
+ if (!this.canAttachCriterion(element, target, position, source)) {
572
+ return false;
573
+ }
574
+
575
+ if (source && isParent(target, source)) {
576
+ return false;
577
+ }
578
+
579
+ // disallow drop entry criterion...
580
+
581
+ // ... on case plan model
582
+ if (isCasePlanModel(target)) {
583
+ return false;
584
+ }
585
+
586
+ if (isPlanFragment(target, true)) {
587
+
588
+ // ... when element has an incoming connection which source
589
+ // is a child of the target
590
+ return !some(element.incoming, function(connection) {
591
+ if (is(connection.businessObject.cmmnElementRef, 'cmmn:PlanItemOnPart')) {
592
+ return isParent(target, connection.source);
593
+ }
594
+ });
595
+
596
+ }
597
+
598
+ return true;
599
+ };
600
+
601
+
602
+ CmmnRules.prototype.canAttachExitCriterion = function(element, target, position, source) {
603
+
604
+ if (!this.canAttachCriterion(element, target, position, source)) {
605
+ return false;
606
+ }
607
+
608
+ // disallow drop exit criterion...
609
+
610
+ // ... on milestone
611
+ if (isMilestone(target)) {
612
+ return false;
613
+ }
614
+
615
+ // ... on non blocking task
616
+ if (isTask(target) && !isBlocking(target)) {
617
+ return false;
618
+ }
619
+
620
+ return true;
621
+
622
+ };
623
+
624
+
625
+ CmmnRules.prototype.canAttachCriterion = function(element, target, position, source) {
626
+
627
+ if (source && isParent(source, target)) {
628
+ return false;
629
+ }
630
+
631
+ // disallow drop criterion...
632
+
633
+ // ... on another criterion
634
+ if (isCriterion(target)) {
635
+ return false;
636
+ }
637
+
638
+ // ... on event listener
639
+ if (isEventListener(target)) {
640
+ return false;
641
+ }
642
+
643
+ // a plan fragment does not have any execution semantic,
644
+ // that why it should not be possible to attach an criterion
645
+ if (isPlanFragment(target)) {
646
+ return false;
647
+ }
648
+
649
+ // ... on a text annotation
650
+ if (isTextAnnotation(target)) {
651
+ return false;
652
+ }
653
+
654
+ // ... on a case file item
655
+ if (isCaseFileItem(target)) {
656
+ return false;
657
+ }
658
+
659
+ // only attach to border
660
+ if (position && !isCriterionAttachment(position, target)) {
661
+ return false;
662
+ }
663
+
664
+ return true;
665
+
666
+ };
667
+
668
+
669
+ CmmnRules.prototype.canReplace = function(elements, target, position, source) {
670
+
671
+ if (!target) {
672
+ return false;
673
+ }
674
+
675
+ if (isSame(source, target)) {
676
+ return false;
677
+ }
678
+
679
+ var canExecute = {
680
+ replacements: []
681
+ };
682
+
683
+ var self = this;
684
+
685
+ forEach(elements, function(element) {
686
+
687
+ if (isEntryCriterion(element) && !self.canAttachEntryCriterion(element, target, position, source)) {
688
+ if (self.canAttachExitCriterion(element, target, position, source)) {
689
+ canExecute.replacements.push({
690
+ oldElementId: element.id,
691
+ newElementType: 'cmmn:ExitCriterion'
692
+ });
693
+ }
694
+ }
695
+
696
+ if (isExitCriterion(element) && !self.canAttachExitCriterion(element, target, position, source)) {
697
+ if (self.canAttachEntryCriterion(element, target, position, source)) {
698
+ canExecute.replacements.push({
699
+ oldElementId: element.id,
700
+ newElementType: 'cmmn:EntryCriterion'
701
+ });
702
+ }
703
+ }
704
+
705
+ if (isPlanFragment(target) &&
706
+ isDiscretionaryItem(element) &&
707
+ self.canDrop(element, target) &&
708
+ !self.canMoveDiscretionaryItem(element, elements, target)) {
709
+
710
+ var replacement = {
711
+ oldElementId: element.id,
712
+ newElementType: 'cmmn:PlanItem'
713
+ };
714
+
715
+ if (isPlanFragment(element)) {
716
+ assign(replacement, {
717
+ newDefinitionType: 'cmmn:Stage'
718
+ });
719
+ }
720
+
721
+ canExecute.replacements.push(replacement);
722
+
723
+ }
724
+
725
+ });
726
+
727
+ return canExecute.replacements.length ? canExecute : false;
728
+ };
729
+
730
+
731
+ CmmnRules.prototype.canReplaceConnectionEnd = function(source, target, side) {
732
+
733
+ if (!source || !target) {
734
+ return false;
735
+ }
736
+
737
+ if (isSame(source, target)) {
738
+ return false;
739
+ }
740
+
741
+ if (!isSameCase(source, target)) {
742
+ return false;
743
+ }
744
+
745
+ return side === 'source' ? this.canReplaceSource(source, target) : this.canReplaceTarget(source, target);
746
+
747
+ };
748
+
749
+
750
+ CmmnRules.prototype.canReplaceSource = function(source, target) {
751
+
752
+ if (isDiscretionaryItem(source) && isCriterion(target)) {
753
+
754
+ if (isSame(source, target.host)) {
755
+ return false;
756
+ }
757
+
758
+ if (isPlanFragment(source)) {
759
+ return false;
760
+ }
761
+
762
+ if (isParent(source, target.host)) {
763
+ return false;
764
+ }
765
+
766
+ if (isEntryCriterion(target) && isParent(target.host, source)) {
767
+ return false;
768
+ }
769
+
770
+ return {
771
+ type: 'cmmn:PlanItemOnPart',
772
+ isStandardEventVisible: true,
773
+ replacements: [{
774
+ oldElementId: source.id,
775
+ newElementType: 'cmmn:PlanItem'
776
+ }]
777
+ };
778
+
779
+ }
780
+
781
+
782
+ if (isEntryCriterion(source) && isEntryCriterion(target)) {
783
+
784
+ if (isSame(source.host, target.host)) {
785
+ return false;
786
+ }
787
+
788
+ if (isParent(target.host, source.host) ||
789
+ isParent(source.host, target.host)) {
790
+ return false;
791
+ }
792
+
793
+ if (hasIncomingOnPartConnections(source)) {
794
+ return false;
795
+ }
796
+
797
+ if (!this.canAttachExitCriterion(source, source.host)) {
798
+ return false;
799
+ }
800
+
801
+ return {
802
+ type: 'cmmn:PlanItemOnPart',
803
+ isStandardEventVisible: true,
804
+ replacements: [{
805
+ oldElementId: source.id,
806
+ newElementType: 'cmmn:ExitCriterion'
807
+ }]
808
+ };
809
+
810
+ }
811
+
812
+ return false;
813
+
814
+ };
815
+
816
+
817
+ CmmnRules.prototype.canReplaceTarget = function(source, target) {
818
+
819
+ if (isHumanTask(getDefinition(source)) && isPlanItem(target)) {
820
+
821
+ if (!isBlocking(source)) {
822
+ return false;
823
+ }
824
+
825
+ if (isEventListener(target) || isMilestone(target)) {
826
+ return false;
827
+ }
828
+
829
+ if (isSameDefinition(source, target)) {
830
+ return false;
831
+ }
832
+
833
+ if (!isSameParent(source, target)) {
834
+ return false;
835
+ }
836
+
837
+ return {
838
+ type: 'cmmndi:CMMNEdge',
839
+ replacements: [{
840
+ oldElementId: target.id,
841
+ newElementType: 'cmmn:DiscretionaryItem'
842
+ }]
843
+ };
844
+
845
+ }
846
+
847
+ if ((isPlanItem(source) || isExitCriterion(source)) && isEntryCriterion(target)) {
848
+
849
+ if (isSame(source.host || source, target.host)) {
850
+ return false;
851
+ }
852
+
853
+ if (!isParent(target.host, source.host || source)) {
854
+ return false;
855
+ }
856
+
857
+ if (hasIncomingOnPartConnections(target)) {
858
+ return false;
859
+ }
860
+
861
+ if (!this.canAttachExitCriterion(target, target.host)) {
862
+ return false;
863
+ }
864
+
865
+ return {
866
+ type: 'cmmn:PlanItemOnPart',
867
+ isStandardEventVisible: true,
868
+ replacements: [{
869
+ oldElementId: target.id,
870
+ newElementType: 'cmmn:ExitCriterion'
871
+ }]
872
+ };
873
+
874
+ }
875
+
876
+ return false;
877
+
878
+ };
879
+
880
+
881
+ CmmnRules.prototype.canSetRepetitionRule = function(element) {
882
+ return isPlanItemControlCapable(element);
883
+ };
884
+
885
+
886
+ CmmnRules.prototype.canSetRequiredRule = function(element) {
887
+ return isPlanItemControlCapable(element);
888
+ };
889
+
890
+
891
+ CmmnRules.prototype.canSetManualActivationRule = function(element) {
892
+ if (isMilestone(element)) {
893
+ return false;
894
+ }
895
+ return isPlanItemControlCapable(element);
896
+ };
897
+
898
+
899
+ /**
900
+ * Utility functions for rule checking
901
+ */
902
+
903
+ /**
904
+ * Checks if given element can be used for starting connection.
905
+ *
906
+ * @param {Element} source
907
+ * @return {Boolean}
908
+ */
909
+ function canStartConnection(element) {
910
+ if (nonExistingOrLabel(element)) {
911
+ return null;
912
+ }
913
+
914
+ return isAny(element, [
915
+ 'cmmn:CaseFileItem',
916
+ 'cmmn:Criterion',
917
+ 'cmmn:DiscretionaryItem',
918
+ 'cmmn:PlanItem'
919
+ ]);
920
+ }
921
+
922
+ function isParent(possibleParent, element) {
923
+ var allParents = getParents(element);
924
+ return allParents.indexOf(possibleParent) !== -1;
925
+ }
926
+
927
+ function isPlanItemControlCapable(element) {
928
+ return isTask(element) || isMilestone(element) || is(getDefinition(element), 'cmmn:Stage');
929
+ }
930
+
931
+ function nonExistingOrLabel(element) {
932
+ return !element || isLabel(element);
933
+ }
934
+
935
+ function isLabel(element) {
936
+ return element.labelTarget;
937
+ }
938
+
939
+ function isConnection(element) {
940
+ return element.waypoints;
941
+ }
942
+
943
+ function isUniqueDiscretionaryConnection(source, target, connection) {
944
+ return !some(target.incoming, function(con) {
945
+ return con !== connection &&
946
+ isDiscretionaryConnection(con) &&
947
+ con.source === source &&
948
+ con.target === target;
949
+ });
950
+ }
951
+
952
+ function hasIncomingDiscretionaryConnections(target, connection) {
953
+ return some(target.incoming, function(con) {
954
+ return con !== connection && isDiscretionaryConnection(con);
955
+ });
956
+ }
957
+
958
+ function isDiscretionaryConnection(connection) {
959
+ return !connection.businessObject.cmmnElementRef;
960
+ }
961
+
962
+ function hasIncomingOnPartConnections(target) {
963
+ return some(target.incoming, function(con) {
964
+ return isOnPartConnection(con);
965
+ });
966
+ }
967
+
968
+ function isOnPartConnection(connection) {
969
+ return is(connection.businessObject.cmmnElementRef, 'cmmn:OnPart');
970
+ }
971
+
972
+ function isPlanFragment(element, isStage) {
973
+ var definition = getDefinition(element) || element;
974
+
975
+ if (!is(definition, 'cmmn:PlanFragment')) {
976
+ return false;
977
+ }
978
+
979
+ if (!isStage && is(definition, 'cmmn:Stage')) {
980
+ return false;
981
+ }
982
+
983
+ return true;
984
+ }
985
+
986
+ function isEventListener(element) {
987
+ return is(getDefinition(element), 'cmmn:EventListener');
988
+ }
989
+
990
+ function isMilestone(element) {
991
+ return is(getDefinition(element), 'cmmn:Milestone');
992
+ }
993
+
994
+ function isTask(element) {
995
+ return is(getDefinition(element), 'cmmn:Task');
996
+ }
997
+
998
+ function isBlocking(element) {
999
+ element = getDefinition(element);
1000
+ return !!(element && element.isBlocking);
1001
+ }
1002
+
1003
+ function isCriterion(element) {
1004
+ return is(element, 'cmmn:Criterion');
1005
+ }
1006
+
1007
+ function isEntryCriterion(element) {
1008
+ return is(element, 'cmmn:EntryCriterion');
1009
+ }
1010
+
1011
+ function isExitCriterion(element) {
1012
+ return is(element, 'cmmn:ExitCriterion');
1013
+ }
1014
+
1015
+ function isArtifact(element) {
1016
+ if (isConnection(element)) {
1017
+ element = element.businessObject.cmmnElementRef;
1018
+ }
1019
+ return is(element, 'cmmn:Artifact');
1020
+ }
1021
+
1022
+ function isTextAnnotation(element) {
1023
+ return is(element, 'cmmn:TextAnnotation');
1024
+ }
1025
+
1026
+ function isCaseFileItem(element) {
1027
+ return is(element, 'cmmn:CaseFileItem');
1028
+ }
1029
+
1030
+ function isPlanItem(element) {
1031
+ return is(element, 'cmmn:PlanItem');
1032
+ }
1033
+
1034
+ function isSameParent(a, b) {
1035
+ return isSame(getParent(a), getParent(b));
1036
+ }
1037
+
1038
+ function isSameDefinition(a, b) {
1039
+ return isSame(getDefinition(a), getDefinition(b));
1040
+ }