@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.
- package/.babelrc +3 -0
- package/CHANGELOG.md +119 -0
- package/LICENSE +23 -0
- package/README.md +107 -2
- package/dist/assets/cmmn-font/css/cmmn-codes.css +41 -0
- package/dist/assets/cmmn-font/css/cmmn-embedded.css +94 -0
- package/dist/assets/cmmn-font/css/cmmn.css +97 -0
- package/dist/assets/cmmn-font/font/cmmn.eot +0 -0
- package/dist/assets/cmmn-font/font/cmmn.svg +90 -0
- package/dist/assets/cmmn-font/font/cmmn.ttf +0 -0
- package/dist/assets/cmmn-font/font/cmmn.woff +0 -0
- package/dist/assets/cmmn-font/font/cmmn.woff2 +0 -0
- package/dist/assets/diagram-js.css +713 -0
- package/dist/cmmn-modeler.development.js +44817 -0
- package/dist/cmmn-modeler.production.min.js +2 -0
- package/dist/cmmn-navigated-viewer.development.js +18131 -0
- package/dist/cmmn-navigated-viewer.production.min.js +2 -0
- package/dist/cmmn-viewer.development.js +17599 -0
- package/dist/cmmn-viewer.production.min.js +2 -0
- package/index.js +1 -0
- package/lib/Modeler.js +222 -0
- package/lib/NavigatedViewer.js +28 -0
- package/lib/Viewer.js +489 -0
- package/lib/core/ItemRegistry.js +316 -0
- package/lib/core/index.js +7 -0
- package/lib/draw/CmmnRenderer.js +1235 -0
- package/lib/draw/PathMap.js +335 -0
- package/lib/draw/index.js +5 -0
- package/lib/features/auto-resize/CmmnAutoResizeProvider.js +57 -0
- package/lib/features/auto-resize/index.js +7 -0
- package/lib/features/context-pad/ContextPadProvider.js +240 -0
- package/lib/features/context-pad/index.js +11 -0
- package/lib/features/editor-actions/CmmnEditorActions.js +105 -0
- package/lib/features/editor-actions/index.js +10 -0
- package/lib/features/keyboard/CmmnKeyboardBindings.js +159 -0
- package/lib/features/keyboard/index.js +7 -0
- package/lib/features/label-editing/LabelEditingProvider.js +221 -0
- package/lib/features/label-editing/LabelUtil.js +95 -0
- package/lib/features/label-editing/cmd/UpdateLabelHandler.js +63 -0
- package/lib/features/label-editing/index.js +9 -0
- package/lib/features/modeling/CmmnFactory.js +166 -0
- package/lib/features/modeling/CmmnLayouter.js +49 -0
- package/lib/features/modeling/CmmnUpdater.js +511 -0
- package/lib/features/modeling/ElementFactory.js +215 -0
- package/lib/features/modeling/Modeling.js +185 -0
- package/lib/features/modeling/behavior/AttachCriterionBehavior.js +58 -0
- package/lib/features/modeling/behavior/CaseFileItemUpdater.js +324 -0
- package/lib/features/modeling/behavior/LabelBehavior.js +139 -0
- package/lib/features/modeling/behavior/PlanItemDefinitionUpdater.js +449 -0
- package/lib/features/modeling/behavior/PlanningTableUpdater.js +620 -0
- package/lib/features/modeling/behavior/ReplaceConnectionBehavior.js +320 -0
- package/lib/features/modeling/behavior/ReplaceElementBehavior.js +395 -0
- package/lib/features/modeling/behavior/ResizeCasePlanModelBehavior.js +108 -0
- package/lib/features/modeling/behavior/SentryUpdater.js +678 -0
- package/lib/features/modeling/behavior/UnclaimIdBehavior.js +28 -0
- package/lib/features/modeling/behavior/index.js +24 -0
- package/lib/features/modeling/cmd/AppendShapeHandler.js +52 -0
- package/lib/features/modeling/cmd/IdClaimHandler.js +38 -0
- package/lib/features/modeling/cmd/ReconnectConnectionHandler.js +57 -0
- package/lib/features/modeling/cmd/ReplaceShapeHandler.js +46 -0
- package/lib/features/modeling/cmd/UpdateControlsHandler.js +221 -0
- package/lib/features/modeling/cmd/UpdatePropertiesHandler.js +240 -0
- package/lib/features/modeling/cmd/UpdateSemanticParentHandler.js +94 -0
- package/lib/features/modeling/index.js +20 -0
- package/lib/features/modeling/util/ModelingUtil.js +138 -0
- package/lib/features/modeling/util/PlanItemDefinitionUtil.js +183 -0
- package/lib/features/ordering/CmmnOrderingProvider.js +146 -0
- package/lib/features/ordering/index.js +4 -0
- package/lib/features/outline/Outline.js +47 -0
- package/lib/features/outline/index.js +6 -0
- package/lib/features/palette/PaletteProvider.js +171 -0
- package/lib/features/palette/index.js +12 -0
- package/lib/features/popup-menu/ReplaceMenuProvider.js +448 -0
- package/lib/features/popup-menu/index.js +4 -0
- package/lib/features/replace/CmmnReplace.js +355 -0
- package/lib/features/replace/ReplaceOptions.js +241 -0
- package/lib/features/replace/index.js +8 -0
- package/lib/features/replace-preview/CmmnReplacePreview.js +247 -0
- package/lib/features/replace-preview/index.js +7 -0
- package/lib/features/rules/CmmnRules.js +1040 -0
- package/lib/features/rules/index.js +7 -0
- package/lib/features/search/CmmnSearchProvider.js +129 -0
- package/lib/features/search/index.js +7 -0
- package/lib/features/snapping/CmmnConnectSnapping.js +110 -0
- package/lib/features/snapping/CmmnCreateMoveSnapping.js +148 -0
- package/lib/features/snapping/CmmnResizeSnapping.js +42 -0
- package/lib/features/snapping/CmmnSnappingUtil.js +76 -0
- package/lib/features/snapping/index.js +17 -0
- package/lib/import/CmmnImporter.js +251 -0
- package/lib/import/CmmnTreeWalker.js +410 -0
- package/lib/import/Importer.js +73 -0
- package/lib/import/Util.js +9 -0
- package/lib/import/index.js +3 -0
- package/lib/util/DiUtil.js +39 -0
- package/lib/util/LabelUtil.js +124 -0
- package/lib/util/ModelUtil.js +257 -0
- package/lib/util/PoweredByUtil.js +91 -0
- package/package.json +88 -4
- package/test/helper/index.js +231 -0
- package/test/util/KeyEvents.js +23 -0
- package/test/util/MockEvents.js +55 -0
- package/test/util/custom-rules/CustomRules.js +19 -0
- 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
|
+
}
|