bpmn-elk-layout 1.2.0 → 1.3.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/dist/bin/bpmn-elk-layout.js +670 -42
- package/dist/bin/bpmn-elk-layout.js.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +670 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +670 -44
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.js +670 -44
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +670 -44
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1251,8 +1251,6 @@ var init_bpmn_constants = __esm({
|
|
|
1251
1251
|
"dataObject",
|
|
1252
1252
|
"dataObjectReference",
|
|
1253
1253
|
"dataStoreReference",
|
|
1254
|
-
"dataInput",
|
|
1255
|
-
"dataOutput",
|
|
1256
1254
|
"textAnnotation"
|
|
1257
1255
|
]);
|
|
1258
1256
|
}
|
|
@@ -2022,10 +2020,13 @@ var init_lane_arranger = __esm({
|
|
|
2022
2020
|
console.log(`[BPMN] targetPos=${JSON.stringify(targetPos)}`);
|
|
2023
2021
|
}
|
|
2024
2022
|
if (sourcePos && targetPos) {
|
|
2025
|
-
const startX
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2023
|
+
const { startX, startY, endX, endY } = this.calculateConnectionPoints(
|
|
2024
|
+
sourcePos,
|
|
2025
|
+
targetPos,
|
|
2026
|
+
sourceId,
|
|
2027
|
+
targetId,
|
|
2028
|
+
nodePositions
|
|
2029
|
+
);
|
|
2029
2030
|
if (isDebugEnabled()) {
|
|
2030
2031
|
console.log(`[BPMN] startX=${startX}, startY=${startY}, endX=${endX}, endY=${endY}`);
|
|
2031
2032
|
}
|
|
@@ -2040,33 +2041,10 @@ var init_lane_arranger = __esm({
|
|
|
2040
2041
|
targetId,
|
|
2041
2042
|
nodePositions
|
|
2042
2043
|
);
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
startY,
|
|
2048
|
-
endX,
|
|
2049
|
-
endY,
|
|
2050
|
-
obstaclesInPath,
|
|
2051
|
-
nodePositions
|
|
2052
|
-
);
|
|
2053
|
-
for (const pt of routePoints) {
|
|
2054
|
-
waypoints.push(pt);
|
|
2055
|
-
}
|
|
2056
|
-
} else {
|
|
2057
|
-
const midX = this.findClearMidX(
|
|
2058
|
-
startX,
|
|
2059
|
-
endX,
|
|
2060
|
-
startY,
|
|
2061
|
-
endY,
|
|
2062
|
-
sourceId,
|
|
2063
|
-
targetId,
|
|
2064
|
-
nodePositions
|
|
2065
|
-
);
|
|
2066
|
-
if (midX !== null) {
|
|
2067
|
-
waypoints.push({ x: midX, y: startY });
|
|
2068
|
-
waypoints.push({ x: midX, y: endY });
|
|
2069
|
-
} else {
|
|
2044
|
+
const isHorizontalFlow = this.isHorizontalConnection(startX, startY, endX, endY, sourcePos, targetPos);
|
|
2045
|
+
if (isHorizontalFlow && Math.abs(startY - endY) > 10 || !isHorizontalFlow && Math.abs(startX - endX) > 10 || obstaclesInPath.length > 0) {
|
|
2046
|
+
if (isHorizontalFlow) {
|
|
2047
|
+
if (obstaclesInPath.length > 0 && Math.abs(startY - endY) <= 10) {
|
|
2070
2048
|
const routePoints = this.routeAroundObstacles(
|
|
2071
2049
|
startX,
|
|
2072
2050
|
startY,
|
|
@@ -2078,6 +2056,50 @@ var init_lane_arranger = __esm({
|
|
|
2078
2056
|
for (const pt of routePoints) {
|
|
2079
2057
|
waypoints.push(pt);
|
|
2080
2058
|
}
|
|
2059
|
+
} else {
|
|
2060
|
+
const midX = this.findClearMidX(
|
|
2061
|
+
startX,
|
|
2062
|
+
endX,
|
|
2063
|
+
startY,
|
|
2064
|
+
endY,
|
|
2065
|
+
sourceId,
|
|
2066
|
+
targetId,
|
|
2067
|
+
nodePositions
|
|
2068
|
+
);
|
|
2069
|
+
if (midX !== null) {
|
|
2070
|
+
waypoints.push({ x: midX, y: startY });
|
|
2071
|
+
waypoints.push({ x: midX, y: endY });
|
|
2072
|
+
} else {
|
|
2073
|
+
const routePoints = this.routeAroundObstacles(
|
|
2074
|
+
startX,
|
|
2075
|
+
startY,
|
|
2076
|
+
endX,
|
|
2077
|
+
endY,
|
|
2078
|
+
obstaclesInPath,
|
|
2079
|
+
nodePositions
|
|
2080
|
+
);
|
|
2081
|
+
for (const pt of routePoints) {
|
|
2082
|
+
waypoints.push(pt);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
} else {
|
|
2087
|
+
const midY = this.findClearMidY(
|
|
2088
|
+
startX,
|
|
2089
|
+
endX,
|
|
2090
|
+
startY,
|
|
2091
|
+
endY,
|
|
2092
|
+
sourceId,
|
|
2093
|
+
targetId,
|
|
2094
|
+
nodePositions
|
|
2095
|
+
);
|
|
2096
|
+
if (midY !== null) {
|
|
2097
|
+
waypoints.push({ x: startX, y: midY });
|
|
2098
|
+
waypoints.push({ x: endX, y: midY });
|
|
2099
|
+
} else {
|
|
2100
|
+
const simpleMidY = (startY + endY) / 2;
|
|
2101
|
+
waypoints.push({ x: startX, y: simpleMidY });
|
|
2102
|
+
waypoints.push({ x: endX, y: simpleMidY });
|
|
2081
2103
|
}
|
|
2082
2104
|
}
|
|
2083
2105
|
}
|
|
@@ -2095,6 +2117,265 @@ var init_lane_arranger = __esm({
|
|
|
2095
2117
|
}
|
|
2096
2118
|
}
|
|
2097
2119
|
}
|
|
2120
|
+
/**
|
|
2121
|
+
* Calculate optimal connection points based on relative node positions.
|
|
2122
|
+
* Chooses the best sides (left/right/top/bottom) to connect nodes to minimize edge crossings.
|
|
2123
|
+
*
|
|
2124
|
+
* For BPMN diagrams, we prefer horizontal connections (left-to-right flow) even for cross-lane edges,
|
|
2125
|
+
* because BPMN processes typically flow horizontally.
|
|
2126
|
+
*/
|
|
2127
|
+
calculateConnectionPoints(sourcePos, targetPos, sourceId, targetId, nodePositions) {
|
|
2128
|
+
const sourceCenterX = sourcePos.x + sourcePos.width / 2;
|
|
2129
|
+
const sourceCenterY = sourcePos.y + sourcePos.height / 2;
|
|
2130
|
+
const targetCenterX = targetPos.x + targetPos.width / 2;
|
|
2131
|
+
const targetCenterY = targetPos.y + targetPos.height / 2;
|
|
2132
|
+
const dx = targetCenterX - sourceCenterX;
|
|
2133
|
+
const dy = targetCenterY - sourceCenterY;
|
|
2134
|
+
let startX, startY, endX, endY;
|
|
2135
|
+
const horizontalDistanceSmall = Math.abs(dx) < 30;
|
|
2136
|
+
const verticalDistanceSignificant = Math.abs(dy) > 50;
|
|
2137
|
+
const isVerticalPrimary = horizontalDistanceSmall && verticalDistanceSignificant;
|
|
2138
|
+
if (!isVerticalPrimary) {
|
|
2139
|
+
startY = sourceCenterY;
|
|
2140
|
+
endY = targetCenterY;
|
|
2141
|
+
if (dx >= 0) {
|
|
2142
|
+
startX = sourcePos.x + sourcePos.width;
|
|
2143
|
+
endX = targetPos.x;
|
|
2144
|
+
} else {
|
|
2145
|
+
startX = sourcePos.x;
|
|
2146
|
+
endX = targetPos.x + targetPos.width;
|
|
2147
|
+
}
|
|
2148
|
+
} else {
|
|
2149
|
+
startX = sourceCenterX;
|
|
2150
|
+
endX = targetCenterX;
|
|
2151
|
+
if (dy >= 0) {
|
|
2152
|
+
startY = sourcePos.y + sourcePos.height;
|
|
2153
|
+
endY = targetPos.y;
|
|
2154
|
+
} else {
|
|
2155
|
+
startY = sourcePos.y;
|
|
2156
|
+
endY = targetPos.y + targetPos.height;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
const directObstacles = this.getObstaclesInPath(
|
|
2160
|
+
startX,
|
|
2161
|
+
startY,
|
|
2162
|
+
endX,
|
|
2163
|
+
endY,
|
|
2164
|
+
sourceId,
|
|
2165
|
+
targetId,
|
|
2166
|
+
nodePositions
|
|
2167
|
+
);
|
|
2168
|
+
if (directObstacles.length > 0) {
|
|
2169
|
+
const alternatives = this.findAlternativeConnectionPoints(
|
|
2170
|
+
sourcePos,
|
|
2171
|
+
targetPos,
|
|
2172
|
+
dx,
|
|
2173
|
+
dy,
|
|
2174
|
+
!isVerticalPrimary,
|
|
2175
|
+
sourceId,
|
|
2176
|
+
targetId,
|
|
2177
|
+
nodePositions
|
|
2178
|
+
);
|
|
2179
|
+
if (alternatives) {
|
|
2180
|
+
return alternatives;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return { startX, startY, endX, endY };
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Find alternative connection points that may have fewer obstacles.
|
|
2187
|
+
*/
|
|
2188
|
+
findAlternativeConnectionPoints(sourcePos, targetPos, dx, dy, isHorizontalPrimary, sourceId, targetId, nodePositions) {
|
|
2189
|
+
const sourceCenterX = sourcePos.x + sourcePos.width / 2;
|
|
2190
|
+
const sourceCenterY = sourcePos.y + sourcePos.height / 2;
|
|
2191
|
+
const targetCenterX = targetPos.x + targetPos.width / 2;
|
|
2192
|
+
const targetCenterY = targetPos.y + targetPos.height / 2;
|
|
2193
|
+
const candidates = [];
|
|
2194
|
+
if (dx >= 0) {
|
|
2195
|
+
candidates.push({
|
|
2196
|
+
startX: sourcePos.x + sourcePos.width,
|
|
2197
|
+
startY: sourceCenterY,
|
|
2198
|
+
endX: targetPos.x,
|
|
2199
|
+
endY: targetCenterY,
|
|
2200
|
+
score: 0
|
|
2201
|
+
});
|
|
2202
|
+
} else {
|
|
2203
|
+
candidates.push({
|
|
2204
|
+
startX: sourcePos.x,
|
|
2205
|
+
startY: sourceCenterY,
|
|
2206
|
+
endX: targetPos.x + targetPos.width,
|
|
2207
|
+
endY: targetCenterY,
|
|
2208
|
+
score: 0
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
if (dy >= 0) {
|
|
2212
|
+
candidates.push({
|
|
2213
|
+
startX: sourceCenterX,
|
|
2214
|
+
startY: sourcePos.y + sourcePos.height,
|
|
2215
|
+
endX: targetCenterX,
|
|
2216
|
+
endY: targetPos.y,
|
|
2217
|
+
score: 0
|
|
2218
|
+
});
|
|
2219
|
+
} else {
|
|
2220
|
+
candidates.push({
|
|
2221
|
+
startX: sourceCenterX,
|
|
2222
|
+
startY: sourcePos.y,
|
|
2223
|
+
endX: targetCenterX,
|
|
2224
|
+
endY: targetPos.y + targetPos.height,
|
|
2225
|
+
score: 0
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2228
|
+
if (dx >= 0 && dy >= 0) {
|
|
2229
|
+
candidates.push({
|
|
2230
|
+
startX: sourcePos.x + sourcePos.width,
|
|
2231
|
+
startY: sourceCenterY,
|
|
2232
|
+
endX: targetCenterX,
|
|
2233
|
+
endY: targetPos.y,
|
|
2234
|
+
score: 0
|
|
2235
|
+
});
|
|
2236
|
+
} else if (dx >= 0 && dy < 0) {
|
|
2237
|
+
candidates.push({
|
|
2238
|
+
startX: sourcePos.x + sourcePos.width,
|
|
2239
|
+
startY: sourceCenterY,
|
|
2240
|
+
endX: targetCenterX,
|
|
2241
|
+
endY: targetPos.y + targetPos.height,
|
|
2242
|
+
score: 0
|
|
2243
|
+
});
|
|
2244
|
+
} else if (dx < 0 && dy >= 0) {
|
|
2245
|
+
candidates.push({
|
|
2246
|
+
startX: sourcePos.x,
|
|
2247
|
+
startY: sourceCenterY,
|
|
2248
|
+
endX: targetCenterX,
|
|
2249
|
+
endY: targetPos.y,
|
|
2250
|
+
score: 0
|
|
2251
|
+
});
|
|
2252
|
+
} else {
|
|
2253
|
+
candidates.push({
|
|
2254
|
+
startX: sourcePos.x,
|
|
2255
|
+
startY: sourceCenterY,
|
|
2256
|
+
endX: targetCenterX,
|
|
2257
|
+
endY: targetPos.y + targetPos.height,
|
|
2258
|
+
score: 0
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
for (const candidate of candidates) {
|
|
2262
|
+
const obstacles = this.getObstaclesInPath(
|
|
2263
|
+
candidate.startX,
|
|
2264
|
+
candidate.startY,
|
|
2265
|
+
candidate.endX,
|
|
2266
|
+
candidate.endY,
|
|
2267
|
+
sourceId,
|
|
2268
|
+
targetId,
|
|
2269
|
+
nodePositions
|
|
2270
|
+
);
|
|
2271
|
+
candidate.score = obstacles.length;
|
|
2272
|
+
}
|
|
2273
|
+
candidates.sort((a, b) => a.score - b.score);
|
|
2274
|
+
const best = candidates[0];
|
|
2275
|
+
if (best && best.score === 0) {
|
|
2276
|
+
return { startX: best.startX, startY: best.startY, endX: best.endX, endY: best.endY };
|
|
2277
|
+
}
|
|
2278
|
+
return null;
|
|
2279
|
+
}
|
|
2280
|
+
/**
|
|
2281
|
+
* Determine if the connection is primarily horizontal or vertical.
|
|
2282
|
+
*/
|
|
2283
|
+
isHorizontalConnection(startX, startY, endX, endY, sourcePos, targetPos) {
|
|
2284
|
+
const isStartOnHorizontalEdge = Math.abs(startX - sourcePos.x) < 1 || Math.abs(startX - (sourcePos.x + sourcePos.width)) < 1;
|
|
2285
|
+
return isStartOnHorizontalEdge;
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Find a clear Y position for horizontal edge segment that avoids obstacles.
|
|
2289
|
+
* Similar to findClearMidX but for vertical flow routing.
|
|
2290
|
+
*/
|
|
2291
|
+
findClearMidY(startX, endX, startY, endY, sourceId, targetId, nodePositions) {
|
|
2292
|
+
const margin = 15;
|
|
2293
|
+
const minX = Math.min(startX, endX);
|
|
2294
|
+
const maxX = Math.max(startX, endX);
|
|
2295
|
+
const rangeMinY = Math.min(startY, endY);
|
|
2296
|
+
const rangeMaxY = Math.max(startY, endY);
|
|
2297
|
+
const flowNodePatterns = [
|
|
2298
|
+
/^task_/,
|
|
2299
|
+
/^gateway_/,
|
|
2300
|
+
/^start_/,
|
|
2301
|
+
/^end_/,
|
|
2302
|
+
/^subprocess_/,
|
|
2303
|
+
/^call_/,
|
|
2304
|
+
/^intermediate_/,
|
|
2305
|
+
/^event_/,
|
|
2306
|
+
/^catch_/
|
|
2307
|
+
];
|
|
2308
|
+
const allObstacles = [];
|
|
2309
|
+
for (const [nodeId, pos] of nodePositions) {
|
|
2310
|
+
if (nodeId === sourceId || nodeId === targetId) continue;
|
|
2311
|
+
if (nodeId.startsWith("lane_")) continue;
|
|
2312
|
+
const isFlowNode = flowNodePatterns.some((pattern) => pattern.test(nodeId));
|
|
2313
|
+
if (!isFlowNode) continue;
|
|
2314
|
+
const nodeLeft = pos.x;
|
|
2315
|
+
const nodeRight = pos.x + pos.width;
|
|
2316
|
+
const nodeTop = pos.y;
|
|
2317
|
+
const nodeBottom = pos.y + pos.height;
|
|
2318
|
+
const yOverlap = nodeBottom > rangeMinY && nodeTop < rangeMaxY;
|
|
2319
|
+
const xOverlapHorizontal = nodeRight > minX && nodeLeft < maxX;
|
|
2320
|
+
const xContainsStartX = nodeLeft <= startX && nodeRight >= startX;
|
|
2321
|
+
const xContainsEndX = nodeLeft <= endX && nodeRight >= endX;
|
|
2322
|
+
if (yOverlap && (xOverlapHorizontal || xContainsStartX || xContainsEndX)) {
|
|
2323
|
+
allObstacles.push({
|
|
2324
|
+
x: nodeLeft,
|
|
2325
|
+
y: nodeTop,
|
|
2326
|
+
width: pos.width,
|
|
2327
|
+
height: pos.height,
|
|
2328
|
+
right: nodeRight,
|
|
2329
|
+
bottom: nodeBottom
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
if (allObstacles.length === 0) {
|
|
2334
|
+
return (startY + endY) / 2;
|
|
2335
|
+
}
|
|
2336
|
+
const isValidMidY = (midY) => {
|
|
2337
|
+
for (const obs of allObstacles) {
|
|
2338
|
+
const seg1MinY = Math.min(startY, midY);
|
|
2339
|
+
const seg1MaxY = Math.max(startY, midY);
|
|
2340
|
+
if (obs.x <= startX && obs.right >= startX && obs.bottom > seg1MinY && obs.y < seg1MaxY) {
|
|
2341
|
+
return false;
|
|
2342
|
+
}
|
|
2343
|
+
if (obs.y <= midY && obs.bottom >= midY && obs.right > minX && obs.x < maxX) {
|
|
2344
|
+
return false;
|
|
2345
|
+
}
|
|
2346
|
+
const seg2MinY = Math.min(midY, endY);
|
|
2347
|
+
const seg2MaxY = Math.max(midY, endY);
|
|
2348
|
+
if (obs.x <= endX && obs.right >= endX && obs.bottom > seg2MinY && obs.y < seg2MaxY) {
|
|
2349
|
+
return false;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
return true;
|
|
2353
|
+
};
|
|
2354
|
+
const candidates = [];
|
|
2355
|
+
candidates.push((startY + endY) / 2);
|
|
2356
|
+
candidates.push(startY + margin);
|
|
2357
|
+
candidates.push(endY - margin);
|
|
2358
|
+
for (const obs of allObstacles) {
|
|
2359
|
+
candidates.push(obs.y - margin);
|
|
2360
|
+
candidates.push(obs.bottom + margin);
|
|
2361
|
+
}
|
|
2362
|
+
const simpleMidY = (startY + endY) / 2;
|
|
2363
|
+
const validCandidates = candidates.filter((y) => y >= rangeMinY && y <= rangeMaxY).sort((a, b) => Math.abs(a - simpleMidY) - Math.abs(b - simpleMidY));
|
|
2364
|
+
for (const candidate of validCandidates) {
|
|
2365
|
+
if (isValidMidY(candidate)) {
|
|
2366
|
+
return candidate;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
const topMost = Math.min(...allObstacles.map((o) => o.y)) - margin;
|
|
2370
|
+
const bottomMost = Math.max(...allObstacles.map((o) => o.bottom)) + margin;
|
|
2371
|
+
if (topMost >= rangeMinY && isValidMidY(topMost)) {
|
|
2372
|
+
return topMost;
|
|
2373
|
+
}
|
|
2374
|
+
if (bottomMost <= rangeMaxY && isValidMidY(bottomMost)) {
|
|
2375
|
+
return bottomMost;
|
|
2376
|
+
}
|
|
2377
|
+
return null;
|
|
2378
|
+
}
|
|
2098
2379
|
/**
|
|
2099
2380
|
* Get obstacles in the direct path from source to target.
|
|
2100
2381
|
* This handles the case where source and target are at similar Y positions
|
|
@@ -3980,6 +4261,23 @@ var init_elk_graph_preparer = __esm({
|
|
|
3980
4261
|
"elk.layered.layering.layerConstraint": "LAST"
|
|
3981
4262
|
};
|
|
3982
4263
|
}
|
|
4264
|
+
const ioSpec = node.bpmn?.ioSpecification;
|
|
4265
|
+
let ioSpecExtraHeight = 0;
|
|
4266
|
+
if (ioSpec) {
|
|
4267
|
+
const dataInputs = ioSpec.dataInputs ?? [];
|
|
4268
|
+
const dataOutputs = ioSpec.dataOutputs ?? [];
|
|
4269
|
+
const maxCount = Math.max(dataInputs.length, dataOutputs.length);
|
|
4270
|
+
if (maxCount > 0) {
|
|
4271
|
+
const dataHeight = 50;
|
|
4272
|
+
const gapBelow = 20;
|
|
4273
|
+
const verticalSpacing = 24;
|
|
4274
|
+
const labelHeight = 14;
|
|
4275
|
+
ioSpecExtraHeight = gapBelow + maxCount * (dataHeight + verticalSpacing) + labelHeight;
|
|
4276
|
+
if (isDebugEnabled()) {
|
|
4277
|
+
console.log(`[BPMN] Adding extra height ${ioSpecExtraHeight} for node ${node.id} with ioSpecification`);
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
3983
4281
|
if (mainFlowNodes.has(node.id) && !boundaryEventTargetIds.has(node.id)) {
|
|
3984
4282
|
layoutOptions = {
|
|
3985
4283
|
...layoutOptions,
|
|
@@ -4059,12 +4357,15 @@ var init_elk_graph_preparer = __esm({
|
|
|
4059
4357
|
"elk.padding": "[top=12,left=12,bottom=12,right=12]"
|
|
4060
4358
|
};
|
|
4061
4359
|
}
|
|
4360
|
+
const originalHeight = node.height ?? 80;
|
|
4361
|
+
const elkHeight = originalHeight + ioSpecExtraHeight;
|
|
4362
|
+
const bpmnWithVisualHeight = ioSpecExtraHeight > 0 ? { ...node.bpmn, _visualHeight: originalHeight } : node.bpmn;
|
|
4062
4363
|
const elkNode = {
|
|
4063
4364
|
id: node.id,
|
|
4064
4365
|
width: node.width,
|
|
4065
|
-
height:
|
|
4366
|
+
height: elkHeight,
|
|
4066
4367
|
layoutOptions,
|
|
4067
|
-
bpmn:
|
|
4368
|
+
bpmn: bpmnWithVisualHeight
|
|
4068
4369
|
};
|
|
4069
4370
|
if (node.children && node.children.length > 0) {
|
|
4070
4371
|
const childNodes = [];
|
|
@@ -4231,12 +4532,16 @@ var init_result_merger = __esm({
|
|
|
4231
4532
|
* Merge a single node's layout results with original BPMN data
|
|
4232
4533
|
*/
|
|
4233
4534
|
mergeNodeResults(original, layouted) {
|
|
4535
|
+
const layoutedBpmn = layouted.bpmn;
|
|
4536
|
+
const visualHeight = layoutedBpmn?._visualHeight;
|
|
4537
|
+
const mergedBpmn = visualHeight !== void 0 ? { ...original.bpmn, _visualHeight: visualHeight } : original.bpmn;
|
|
4234
4538
|
const result = {
|
|
4235
4539
|
...original,
|
|
4236
4540
|
x: layouted.x ?? 0,
|
|
4237
4541
|
y: layouted.y ?? 0,
|
|
4238
4542
|
width: layouted.width ?? original.width,
|
|
4239
|
-
height: layouted.height ?? original.height
|
|
4543
|
+
height: layouted.height ?? original.height,
|
|
4544
|
+
bpmn: mergedBpmn
|
|
4240
4545
|
};
|
|
4241
4546
|
if (original.children && layouted.children) {
|
|
4242
4547
|
const layoutedChildMap = new Map(layouted.children.map((c) => [c.id, c]));
|
|
@@ -4898,23 +5203,36 @@ var init_diagram_builder = __esm({
|
|
|
4898
5203
|
const absoluteX = offsetX + node.x;
|
|
4899
5204
|
const absoluteY = offsetY + node.y;
|
|
4900
5205
|
const nodeWidth = node.width ?? 100;
|
|
4901
|
-
const
|
|
5206
|
+
const bpmnAny = node.bpmn;
|
|
5207
|
+
const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 80;
|
|
4902
5208
|
let effectiveHeight = nodeHeight;
|
|
4903
5209
|
if (this.isEventType(node.bpmn?.type) && node.labels && node.labels.length > 0) {
|
|
4904
5210
|
const labelHeight = node.labels[0]?.height ?? 14;
|
|
4905
5211
|
effectiveHeight = nodeHeight + 4 + labelHeight;
|
|
4906
5212
|
}
|
|
4907
|
-
|
|
5213
|
+
const nodePosition = {
|
|
4908
5214
|
x: absoluteX,
|
|
4909
5215
|
y: absoluteY,
|
|
4910
5216
|
width: nodeWidth,
|
|
4911
5217
|
height: effectiveHeight
|
|
4912
|
-
}
|
|
5218
|
+
};
|
|
5219
|
+
if (bpmnAny?._visualHeight !== void 0) {
|
|
5220
|
+
nodePosition.visualHeight = bpmnAny._visualHeight;
|
|
5221
|
+
}
|
|
5222
|
+
this.nodePositions.set(node.id, nodePosition);
|
|
4913
5223
|
if (node.bpmn) {
|
|
4914
5224
|
this.storeNodeBpmn(node.id, { type: node.bpmn.type });
|
|
4915
5225
|
}
|
|
4916
5226
|
this.nodeOffsets.set(node.id, { x: offsetX, y: offsetY });
|
|
4917
5227
|
shapes.push(this.buildShape(node, offsetX, offsetY));
|
|
5228
|
+
const nodeType = node.bpmn?.type;
|
|
5229
|
+
const isTaskOrActivity = nodeType && (nodeType.includes("Task") || nodeType === "task" || nodeType === "callActivity" || nodeType === "subProcess" || nodeType === "transaction" || nodeType === "adHocSubProcess");
|
|
5230
|
+
if (isTaskOrActivity) {
|
|
5231
|
+
const ioSpec = node.bpmn?.ioSpecification;
|
|
5232
|
+
if (ioSpec) {
|
|
5233
|
+
this.buildIoSpecificationShapes(node, ioSpec, shapes, edges, absoluteX, absoluteY, nodeWidth, nodeHeight);
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
4918
5236
|
}
|
|
4919
5237
|
const isExpandedSubprocess = node.bpmn?.isExpanded === true && (node.bpmn?.type === "subProcess" || node.bpmn?.type === "transaction" || node.bpmn?.type === "adHocSubProcess" || node.bpmn?.type === "eventSubProcess" || node.bpmn?.triggeredByEvent === true);
|
|
4920
5238
|
const isPoolOrLane = node.bpmn?.type === "participant" || node.bpmn?.type === "lane";
|
|
@@ -4998,6 +5316,131 @@ var init_diagram_builder = __esm({
|
|
|
4998
5316
|
storeNodeBpmn(nodeId, bpmn) {
|
|
4999
5317
|
this.nodeBpmn.set(nodeId, bpmn);
|
|
5000
5318
|
}
|
|
5319
|
+
/**
|
|
5320
|
+
* Build shapes for ioSpecification dataInputs and dataOutputs
|
|
5321
|
+
* Positions: dataInputs below-left of the task (stacked vertically),
|
|
5322
|
+
* dataOutputs below-right of the task (stacked vertically)
|
|
5323
|
+
* Only the topmost item in each stack has a dashed association edge to the task
|
|
5324
|
+
*/
|
|
5325
|
+
buildIoSpecificationShapes(node, ioSpec, shapes, edges, taskX, taskY, taskWidth, taskHeight) {
|
|
5326
|
+
const dataWidth = 36;
|
|
5327
|
+
const dataHeight = 50;
|
|
5328
|
+
const gapBelow = 20;
|
|
5329
|
+
const verticalSpacing = 24;
|
|
5330
|
+
const labelHeight = 14;
|
|
5331
|
+
const dataInputs = ioSpec.dataInputs ?? [];
|
|
5332
|
+
const inputStartX = taskX;
|
|
5333
|
+
dataInputs.forEach((dataInput, index) => {
|
|
5334
|
+
const inputId = dataInput.id ?? `${node.id}_input_${index}`;
|
|
5335
|
+
const inputX = inputStartX;
|
|
5336
|
+
const inputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);
|
|
5337
|
+
this.nodePositions.set(inputId, {
|
|
5338
|
+
x: inputX,
|
|
5339
|
+
y: inputY,
|
|
5340
|
+
width: dataWidth,
|
|
5341
|
+
height: dataHeight
|
|
5342
|
+
});
|
|
5343
|
+
const shape = {
|
|
5344
|
+
id: `${inputId}_di`,
|
|
5345
|
+
bpmnElement: inputId,
|
|
5346
|
+
bounds: {
|
|
5347
|
+
x: inputX,
|
|
5348
|
+
y: inputY,
|
|
5349
|
+
width: dataWidth,
|
|
5350
|
+
height: dataHeight
|
|
5351
|
+
}
|
|
5352
|
+
};
|
|
5353
|
+
if (dataInput.name) {
|
|
5354
|
+
const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataInput.name));
|
|
5355
|
+
shape.label = {
|
|
5356
|
+
bounds: {
|
|
5357
|
+
x: inputX + (dataWidth - labelWidth) / 2,
|
|
5358
|
+
y: inputY + dataHeight + 4,
|
|
5359
|
+
width: labelWidth,
|
|
5360
|
+
height: labelHeight
|
|
5361
|
+
}
|
|
5362
|
+
};
|
|
5363
|
+
}
|
|
5364
|
+
shapes.push(shape);
|
|
5365
|
+
if (index === 0) {
|
|
5366
|
+
const assocId = `${inputId}_assoc`;
|
|
5367
|
+
const inputCenterX = inputX + dataWidth / 2;
|
|
5368
|
+
const inputTopY = inputY;
|
|
5369
|
+
const taskBottomY = taskY + taskHeight;
|
|
5370
|
+
edges.push({
|
|
5371
|
+
id: `${assocId}_di`,
|
|
5372
|
+
bpmnElement: assocId,
|
|
5373
|
+
waypoints: [
|
|
5374
|
+
{ x: inputCenterX, y: inputTopY },
|
|
5375
|
+
{ x: inputCenterX, y: taskBottomY }
|
|
5376
|
+
]
|
|
5377
|
+
});
|
|
5378
|
+
}
|
|
5379
|
+
});
|
|
5380
|
+
const dataOutputs = ioSpec.dataOutputs ?? [];
|
|
5381
|
+
const outputStartX = taskX + taskWidth - dataWidth;
|
|
5382
|
+
dataOutputs.forEach((dataOutput, index) => {
|
|
5383
|
+
const outputId = dataOutput.id ?? `${node.id}_output_${index}`;
|
|
5384
|
+
const outputX = outputStartX;
|
|
5385
|
+
const outputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);
|
|
5386
|
+
this.nodePositions.set(outputId, {
|
|
5387
|
+
x: outputX,
|
|
5388
|
+
y: outputY,
|
|
5389
|
+
width: dataWidth,
|
|
5390
|
+
height: dataHeight
|
|
5391
|
+
});
|
|
5392
|
+
const shape = {
|
|
5393
|
+
id: `${outputId}_di`,
|
|
5394
|
+
bpmnElement: outputId,
|
|
5395
|
+
bounds: {
|
|
5396
|
+
x: outputX,
|
|
5397
|
+
y: outputY,
|
|
5398
|
+
width: dataWidth,
|
|
5399
|
+
height: dataHeight
|
|
5400
|
+
}
|
|
5401
|
+
};
|
|
5402
|
+
if (dataOutput.name) {
|
|
5403
|
+
const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataOutput.name));
|
|
5404
|
+
shape.label = {
|
|
5405
|
+
bounds: {
|
|
5406
|
+
x: outputX + (dataWidth - labelWidth) / 2,
|
|
5407
|
+
y: outputY + dataHeight + 4,
|
|
5408
|
+
width: labelWidth,
|
|
5409
|
+
height: labelHeight
|
|
5410
|
+
}
|
|
5411
|
+
};
|
|
5412
|
+
}
|
|
5413
|
+
shapes.push(shape);
|
|
5414
|
+
if (index === 0) {
|
|
5415
|
+
const assocId = `${outputId}_assoc`;
|
|
5416
|
+
const outputCenterX = outputX + dataWidth / 2;
|
|
5417
|
+
const outputTopY = outputY;
|
|
5418
|
+
const taskBottomY = taskY + taskHeight;
|
|
5419
|
+
edges.push({
|
|
5420
|
+
id: `${assocId}_di`,
|
|
5421
|
+
bpmnElement: assocId,
|
|
5422
|
+
waypoints: [
|
|
5423
|
+
{ x: outputCenterX, y: taskBottomY },
|
|
5424
|
+
{ x: outputCenterX, y: outputTopY }
|
|
5425
|
+
]
|
|
5426
|
+
});
|
|
5427
|
+
}
|
|
5428
|
+
});
|
|
5429
|
+
}
|
|
5430
|
+
/**
|
|
5431
|
+
* Estimate text width for label sizing (simplified)
|
|
5432
|
+
*/
|
|
5433
|
+
estimateTextWidth(text) {
|
|
5434
|
+
let width = 0;
|
|
5435
|
+
for (const char of text) {
|
|
5436
|
+
if (char.charCodeAt(0) > 255) {
|
|
5437
|
+
width += 14;
|
|
5438
|
+
} else {
|
|
5439
|
+
width += 7;
|
|
5440
|
+
}
|
|
5441
|
+
}
|
|
5442
|
+
return Math.max(36, Math.min(width, 150));
|
|
5443
|
+
}
|
|
5001
5444
|
/**
|
|
5002
5445
|
* Find node BPMN metadata by id
|
|
5003
5446
|
*/
|
|
@@ -5029,6 +5472,8 @@ var init_diagram_builder = __esm({
|
|
|
5029
5472
|
buildShape(node, offsetX = 0, offsetY = 0) {
|
|
5030
5473
|
const absoluteX = offsetX + (node.x ?? 0);
|
|
5031
5474
|
const absoluteY = offsetY + (node.y ?? 0);
|
|
5475
|
+
const bpmnAny = node.bpmn;
|
|
5476
|
+
const visualHeight = bpmnAny?._visualHeight ?? node.height ?? 80;
|
|
5032
5477
|
const shape = {
|
|
5033
5478
|
id: `${node.id}_di`,
|
|
5034
5479
|
bpmnElement: node.id,
|
|
@@ -5036,7 +5481,7 @@ var init_diagram_builder = __esm({
|
|
|
5036
5481
|
x: absoluteX,
|
|
5037
5482
|
y: absoluteY,
|
|
5038
5483
|
width: node.width ?? 100,
|
|
5039
|
-
height:
|
|
5484
|
+
height: visualHeight
|
|
5040
5485
|
}
|
|
5041
5486
|
};
|
|
5042
5487
|
if (node.bpmn?.isExpanded !== void 0) {
|
|
@@ -5046,7 +5491,7 @@ var init_diagram_builder = __esm({
|
|
|
5046
5491
|
shape.isHorizontal = true;
|
|
5047
5492
|
}
|
|
5048
5493
|
const nodeWidth = node.width ?? 36;
|
|
5049
|
-
const nodeHeight = node.height ?? 36;
|
|
5494
|
+
const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 36;
|
|
5050
5495
|
const label = node.labels?.[0];
|
|
5051
5496
|
const labelText = node.bpmn?.name ?? label?.text ?? "";
|
|
5052
5497
|
if (this.isEventType(node.bpmn?.type) && labelText) {
|
|
@@ -5174,6 +5619,7 @@ var init_diagram_builder = __esm({
|
|
|
5174
5619
|
}
|
|
5175
5620
|
}
|
|
5176
5621
|
}
|
|
5622
|
+
this.adjustEndpointsForVisualHeight(waypoints, sourceId, targetId);
|
|
5177
5623
|
}
|
|
5178
5624
|
this.ensureOrthogonalWaypoints(waypoints);
|
|
5179
5625
|
this.ensurePerpendicularEndpoints(
|
|
@@ -5216,6 +5662,66 @@ var init_diagram_builder = __esm({
|
|
|
5216
5662
|
}
|
|
5217
5663
|
return edgeModel;
|
|
5218
5664
|
}
|
|
5665
|
+
/**
|
|
5666
|
+
* Adjust edge endpoints for nodes with ioSpecification (visualHeight)
|
|
5667
|
+
*
|
|
5668
|
+
* When a node has ioSpecification, ELK uses an enlarged height for layout (to make space for data objects).
|
|
5669
|
+
* However, the edge endpoints should connect to the visual node border, not based on the layout height.
|
|
5670
|
+
*
|
|
5671
|
+
* This method adjusts endpoint Y coordinates and also adjusts adjacent waypoints if they were
|
|
5672
|
+
* on the same horizontal line, to maintain horizontal segments without introducing extra bends.
|
|
5673
|
+
*/
|
|
5674
|
+
adjustEndpointsForVisualHeight(waypoints, sourceId, targetId) {
|
|
5675
|
+
if (waypoints.length < 2) return;
|
|
5676
|
+
const tolerance = 5;
|
|
5677
|
+
if (sourceId) {
|
|
5678
|
+
const sourcePos = this.nodePositions.get(sourceId);
|
|
5679
|
+
if (sourcePos?.visualHeight !== void 0) {
|
|
5680
|
+
const firstWp = waypoints[0];
|
|
5681
|
+
const secondWp = waypoints[1];
|
|
5682
|
+
if (firstWp && secondWp) {
|
|
5683
|
+
const nodeRight = sourcePos.x + sourcePos.width;
|
|
5684
|
+
const nodeLeft = sourcePos.x;
|
|
5685
|
+
const visualBottom = sourcePos.y + sourcePos.visualHeight;
|
|
5686
|
+
const visualCenterY = sourcePos.y + sourcePos.visualHeight / 2;
|
|
5687
|
+
if (Math.abs(firstWp.x - nodeRight) < tolerance || Math.abs(firstWp.x - nodeLeft) < tolerance) {
|
|
5688
|
+
const oldY = firstWp.y;
|
|
5689
|
+
const newY = visualCenterY;
|
|
5690
|
+
firstWp.y = newY;
|
|
5691
|
+
if (Math.abs(secondWp.y - oldY) < tolerance && waypoints.length > 2) {
|
|
5692
|
+
secondWp.y = newY;
|
|
5693
|
+
}
|
|
5694
|
+
} else if (firstWp.y > visualBottom) {
|
|
5695
|
+
firstWp.y = visualBottom;
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
}
|
|
5699
|
+
}
|
|
5700
|
+
if (targetId) {
|
|
5701
|
+
const targetPos = this.nodePositions.get(targetId);
|
|
5702
|
+
if (targetPos?.visualHeight !== void 0) {
|
|
5703
|
+
const lastIdx = waypoints.length - 1;
|
|
5704
|
+
const lastWp = waypoints[lastIdx];
|
|
5705
|
+
const prevWp = waypoints[lastIdx - 1];
|
|
5706
|
+
if (lastWp && prevWp) {
|
|
5707
|
+
const nodeLeft = targetPos.x;
|
|
5708
|
+
const nodeRight = targetPos.x + targetPos.width;
|
|
5709
|
+
const visualBottom = targetPos.y + targetPos.visualHeight;
|
|
5710
|
+
const visualCenterY = targetPos.y + targetPos.visualHeight / 2;
|
|
5711
|
+
if (Math.abs(lastWp.x - nodeLeft) < tolerance || Math.abs(lastWp.x - nodeRight) < tolerance) {
|
|
5712
|
+
const oldY = lastWp.y;
|
|
5713
|
+
const newY = visualCenterY;
|
|
5714
|
+
lastWp.y = newY;
|
|
5715
|
+
if (Math.abs(prevWp.y - oldY) < tolerance && waypoints.length > 2) {
|
|
5716
|
+
prevWp.y = newY;
|
|
5717
|
+
}
|
|
5718
|
+
} else if (lastWp.y > visualBottom) {
|
|
5719
|
+
lastWp.y = visualBottom;
|
|
5720
|
+
}
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5219
5725
|
/**
|
|
5220
5726
|
* Calculate smart label position on the edge
|
|
5221
5727
|
* Strategy:
|
|
@@ -5696,7 +6202,7 @@ var init_model_builder = __esm({
|
|
|
5696
6202
|
buildFlowElement(node) {
|
|
5697
6203
|
const incoming = this.refResolver.getIncomingSequenceFlows(node.id);
|
|
5698
6204
|
const outgoing = this.refResolver.getOutgoingSequenceFlows(node.id);
|
|
5699
|
-
|
|
6205
|
+
const flowElement = {
|
|
5700
6206
|
type: node.bpmn?.type ?? "task",
|
|
5701
6207
|
id: node.id,
|
|
5702
6208
|
name: node.bpmn?.name,
|
|
@@ -5704,6 +6210,76 @@ var init_model_builder = __esm({
|
|
|
5704
6210
|
outgoing,
|
|
5705
6211
|
properties: this.extractProperties(node.bpmn ?? {})
|
|
5706
6212
|
};
|
|
6213
|
+
const ioSpec = node.bpmn?.ioSpecification;
|
|
6214
|
+
if (ioSpec) {
|
|
6215
|
+
flowElement.ioSpecification = this.buildIoSpecification(ioSpec, node.id);
|
|
6216
|
+
const dataInputs = ioSpec.dataInputs ?? [];
|
|
6217
|
+
if (dataInputs.length > 0) {
|
|
6218
|
+
const firstInput = dataInputs[0];
|
|
6219
|
+
flowElement.dataInputAssociations = [{
|
|
6220
|
+
id: `${firstInput.id ?? `${node.id}_input_0`}_assoc`,
|
|
6221
|
+
sourceRef: firstInput.id ?? `${node.id}_input_0`,
|
|
6222
|
+
targetRef: node.id
|
|
6223
|
+
}];
|
|
6224
|
+
}
|
|
6225
|
+
const dataOutputs = ioSpec.dataOutputs ?? [];
|
|
6226
|
+
if (dataOutputs.length > 0) {
|
|
6227
|
+
const firstOutput = dataOutputs[0];
|
|
6228
|
+
flowElement.dataOutputAssociations = [{
|
|
6229
|
+
id: `${firstOutput.id ?? `${node.id}_output_0`}_assoc`,
|
|
6230
|
+
sourceRef: node.id,
|
|
6231
|
+
targetRef: firstOutput.id ?? `${node.id}_output_0`
|
|
6232
|
+
}];
|
|
6233
|
+
}
|
|
6234
|
+
}
|
|
6235
|
+
return flowElement;
|
|
6236
|
+
}
|
|
6237
|
+
/**
|
|
6238
|
+
* Build ioSpecification model from input
|
|
6239
|
+
*/
|
|
6240
|
+
buildIoSpecification(ioSpec, taskId) {
|
|
6241
|
+
const dataInputs = (ioSpec.dataInputs ?? []).map((di, index) => ({
|
|
6242
|
+
id: di.id ?? `${taskId}_input_${index}`,
|
|
6243
|
+
name: di.name,
|
|
6244
|
+
itemSubjectRef: di.itemSubjectRef,
|
|
6245
|
+
isCollection: di.isCollection
|
|
6246
|
+
}));
|
|
6247
|
+
const dataOutputs = (ioSpec.dataOutputs ?? []).map((dout, index) => ({
|
|
6248
|
+
id: dout.id ?? `${taskId}_output_${index}`,
|
|
6249
|
+
name: dout.name,
|
|
6250
|
+
itemSubjectRef: dout.itemSubjectRef,
|
|
6251
|
+
isCollection: dout.isCollection
|
|
6252
|
+
}));
|
|
6253
|
+
const inputSets = (ioSpec.inputSets ?? []).map((is, index) => ({
|
|
6254
|
+
id: is.id ?? `${taskId}_inputSet_${index}`,
|
|
6255
|
+
name: is.name,
|
|
6256
|
+
dataInputRefs: is.dataInputRefs ?? []
|
|
6257
|
+
}));
|
|
6258
|
+
if (inputSets.length === 0 && dataInputs.length > 0) {
|
|
6259
|
+
inputSets.push({
|
|
6260
|
+
id: `${taskId}_inputSet_0`,
|
|
6261
|
+
name: void 0,
|
|
6262
|
+
dataInputRefs: dataInputs.map((di) => di.id)
|
|
6263
|
+
});
|
|
6264
|
+
}
|
|
6265
|
+
const outputSets = (ioSpec.outputSets ?? []).map((os, index) => ({
|
|
6266
|
+
id: os.id ?? `${taskId}_outputSet_${index}`,
|
|
6267
|
+
name: os.name,
|
|
6268
|
+
dataOutputRefs: os.dataOutputRefs ?? []
|
|
6269
|
+
}));
|
|
6270
|
+
if (outputSets.length === 0 && dataOutputs.length > 0) {
|
|
6271
|
+
outputSets.push({
|
|
6272
|
+
id: `${taskId}_outputSet_0`,
|
|
6273
|
+
name: void 0,
|
|
6274
|
+
dataOutputRefs: dataOutputs.map((dout) => dout.id)
|
|
6275
|
+
});
|
|
6276
|
+
}
|
|
6277
|
+
return {
|
|
6278
|
+
dataInputs,
|
|
6279
|
+
dataOutputs,
|
|
6280
|
+
inputSets,
|
|
6281
|
+
outputSets
|
|
6282
|
+
};
|
|
5707
6283
|
}
|
|
5708
6284
|
/**
|
|
5709
6285
|
* Build a boundary event model
|
|
@@ -6037,6 +6613,9 @@ var init_bpmn_xml_generator = __esm({
|
|
|
6037
6613
|
}
|
|
6038
6614
|
if (element.type.includes("Task") || element.type === "task") {
|
|
6039
6615
|
this.applyTaskProperties(bpmnElement, props);
|
|
6616
|
+
if (element.ioSpecification) {
|
|
6617
|
+
bpmnElement.ioSpecification = this.buildIoSpecification(element.ioSpecification);
|
|
6618
|
+
}
|
|
6040
6619
|
}
|
|
6041
6620
|
if (element.type.includes("Gateway")) {
|
|
6042
6621
|
this.applyGatewayProperties(bpmnElement, props);
|
|
@@ -6229,6 +6808,55 @@ var init_bpmn_xml_generator = __esm({
|
|
|
6229
6808
|
});
|
|
6230
6809
|
}
|
|
6231
6810
|
}
|
|
6811
|
+
/**
|
|
6812
|
+
* Build ioSpecification element
|
|
6813
|
+
*/
|
|
6814
|
+
buildIoSpecification(ioSpec) {
|
|
6815
|
+
const ioSpecElement = this.moddle.create("bpmn:InputOutputSpecification", {});
|
|
6816
|
+
if (ioSpec.dataInputs.length > 0) {
|
|
6817
|
+
ioSpecElement.dataInputs = ioSpec.dataInputs.map((di) => {
|
|
6818
|
+
return this.moddle.create("bpmn:DataInput", {
|
|
6819
|
+
id: di.id,
|
|
6820
|
+
name: di.name,
|
|
6821
|
+
isCollection: di.isCollection
|
|
6822
|
+
});
|
|
6823
|
+
});
|
|
6824
|
+
}
|
|
6825
|
+
if (ioSpec.dataOutputs.length > 0) {
|
|
6826
|
+
ioSpecElement.dataOutputs = ioSpec.dataOutputs.map((dout) => {
|
|
6827
|
+
return this.moddle.create("bpmn:DataOutput", {
|
|
6828
|
+
id: dout.id,
|
|
6829
|
+
name: dout.name,
|
|
6830
|
+
isCollection: dout.isCollection
|
|
6831
|
+
});
|
|
6832
|
+
});
|
|
6833
|
+
}
|
|
6834
|
+
if (ioSpec.inputSets.length > 0) {
|
|
6835
|
+
ioSpecElement.inputSets = ioSpec.inputSets.map((is) => {
|
|
6836
|
+
const inputSet = this.moddle.create("bpmn:InputSet", {
|
|
6837
|
+
id: is.id,
|
|
6838
|
+
name: is.name
|
|
6839
|
+
});
|
|
6840
|
+
if (is.dataInputRefs.length > 0) {
|
|
6841
|
+
inputSet.dataInputRefs = is.dataInputRefs.map((ref) => ({ id: ref }));
|
|
6842
|
+
}
|
|
6843
|
+
return inputSet;
|
|
6844
|
+
});
|
|
6845
|
+
}
|
|
6846
|
+
if (ioSpec.outputSets.length > 0) {
|
|
6847
|
+
ioSpecElement.outputSets = ioSpec.outputSets.map((os) => {
|
|
6848
|
+
const outputSet = this.moddle.create("bpmn:OutputSet", {
|
|
6849
|
+
id: os.id,
|
|
6850
|
+
name: os.name
|
|
6851
|
+
});
|
|
6852
|
+
if (os.dataOutputRefs.length > 0) {
|
|
6853
|
+
outputSet.dataOutputRefs = os.dataOutputRefs.map((ref) => ({ id: ref }));
|
|
6854
|
+
}
|
|
6855
|
+
return outputSet;
|
|
6856
|
+
});
|
|
6857
|
+
}
|
|
6858
|
+
return ioSpecElement;
|
|
6859
|
+
}
|
|
6232
6860
|
/**
|
|
6233
6861
|
* Apply data associations (BPMN 2.0 spec: dataInputAssociation/dataOutputAssociation are child elements of Activity)
|
|
6234
6862
|
*/
|