diagram.lib.scenario.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common-base Show documentation
Show all versions of common-base Show documentation
DSL based modeling framework - facilities common base
var graph;
function queryParameter(parameterName) {
let query = window.location.search.substring(1);
let parms = query.split('&');
for (let i = 0; i < parms.length; i++) {
let pos = parms[i].indexOf('=');
if (pos > 0 && parameterName == parms[i].substring(0, pos)) {
return parms[i].substring(pos + 1).replace(/%22/g, '');
}
}
return undefined;
}
function collectBases(currentObject, all, hierarchyObjects) {
let currentBase = currentObject.extends;
if (currentBase !== undefined) {
for (let object of all) {
if (object.name === currentBase) {
hierarchyObjects.push(object);
collectBases(object, all, hierarchyObjects);
return;
}
}
}
}
function composeOpenApiUrl(componentNamespace, componentName, controllerTag, operation) {
const tag = controllerTag ? controllerTag : 'default'
return '../../api/' + componentNamespace + '_' + componentName.toLowerCase() +'.html#/'+tag+'/'+operation.operationId
}
function determineComponentPath(data) {
if (window.location.href.includes("diagram/processes/")) {
return "../" + data.applicationName.toLowerCase() + ".html";
} else {
return "../../" + data.applicationName.toLowerCase() + ".html";
}
}
function draw(graph, parent, layout, data) {
let actorVertexes = {};
let componentVertexes1 = {};
let sizing = {
currentX: 0,
currentY: 0
}
let objMap = {}
let interactionMap = {}
let interactions = data.interactions
let componentMap = {}
let components = data.components
if (components) {
for (let component of components) {
componentMap[component.name] = component;
}
}
let infoHeight = 30
if (data.interfaceType == 'REST') {
let doc = mxUtils.createXmlDocument()
let infoNode = doc.createElement('info')
/* OpenApi */
const operation = {
operationId: data.operationId
}
const operationLabel = '' +data.verb + ' ' + data.path
const operationUrl = composeOpenApiUrl(data.componentNamespace, data.componentName, data.controllerTag, operation)
const operationLink = ""+operationLabel+""
/* controller */
const lastDotIndex = data.controller.lastIndexOf('.')
const controllerShort = lastDotIndex > 0 ? data.controller.substring(lastDotIndex + 1 ) : data.controller
const controllerUrl = composeControllerUrl(data.componentNamespace, data.componentName, data.controller)
const controllerLink = "" + controllerShort + ""
let infoHtml = operationLink + '
' + controllerLink
let htmlSize = mxUtils.getSizeForString(infoHtml, null, null,900)
infoNode.setAttribute('label', infoHtml)
let vInfo = graph.insertVertex(parent, null, infoNode, 0, 0, 900, htmlSize.height, 'infoStyle');
vInfo.geometry.offset = new mxPoint(-20, -25);
sizing.currentY = htmlSize.height + 25
}
let actors = data.actors
if (actors) {
for (let actor of actors) {
drawActor(graph, parent, sizing, actor, objMap, actorVertexes, 'actor');
sizing.currentX = sizing.currentX + 150;
}
sizing.currentX = sizing.currentX + 50;
}
const componentsPath = determineComponentPath(data)
if (components) {
for (let component of components) {
drawComponent(graph, parent, parent, sizing, componentsPath, component, objMap, null, 'actor');
}
}
let allComponents = []
collectComponentsRecursive(allComponents, components)
for (let id in objMap) {
let obj = objMap[id]
if (obj.vertex.geometry.offset) {
obj.top = obj.vertex.geometry.offset.y
}
}
let allInteractions = []
collectInteractionsRecursive(allInteractions, interactions)
for (let interaction of allInteractions) {
let fromId = interaction.from
let fromInfo = objMap[fromId]
let maxTextWidth = 295
if (interaction.reference || interaction.note) {
maxTextWidth = 400
}
if (interaction.note) {
maxTextWidth = null
}
if (interaction.execution) {
maxTextWidth = 230
}
let interactionLabel = interaction.name
if (!interaction.hasLabel && interaction.verb && interaction.path) {
interactionLabel = ''+interaction.verb +' '+interaction.path
}
let calculatedLabelSize = mxUtils.getSizeForString(interactionLabel, null, null,maxTextWidth)
if (calculatedLabelSize.width > 500) {
calculatedLabelSize = mxUtils.getSizeForString(interactionLabel, null, null,500)
}
const nestedLevels = determineNestedLevels(interaction)
const interactionInfo = {
name: interactionLabel,
interaction: interaction,
labelSize: calculatedLabelSize,
nestedLevels: nestedLevels
}
if (interaction.result) {
interactionInfo.resultLabelSize = mxUtils.getSizeForString(interaction.result, null, null,maxTextWidth)
} else {
interactionInfo.resultLabelSize = new mxRectangle(0, 0, 0, 0)
}
if (fromInfo) {
fromInfo.interactions.push(interactionInfo)
}
interactionMap[interaction.id] = interactionInfo
}
let interactionSizing = {
index: 0,
top: sizing.currentY + 70,
currentTop: sizing.currentY + 70,
distance: 15,
executionBoxSpace: 12,
selfHeight: 25,
selfWidth: 80
}
if (interactions) {
let allParticipants = new Set();
for (let participantId in objMap) {
const participantInfo = objMap[participantId]
allParticipants.add(participantInfo)
}
const ctx = {
children: allParticipants,
leftParticipant: determineLeftParticipant(allParticipants),
rightParticipant: determineRightParticipant(allParticipants)
}
let i=-1
for (const interaction in allInteractions) {
i++
const interaction = allInteractions[i]
let interactionInfo = interactionMap[interaction.id]
if (interactionInfo.interaction.condition && !interactionInfo.interaction.else) {
let maxNestedLevels = interactionInfo.nestedLevels
let elseBranchInfos = []
let childParticipants = new Set();
determineChildParticipants(childParticipants, interactionInfo.interaction, objMap)
let prevInteractionInfo = interactionInfo
let current = interactionInfo.interaction
while (current && current.nextInteraction) {
if (current.nextInteraction.condition && current.nextInteraction.else) {
current = current.nextInteraction
let nextInteractionInfo = interactionMap[current.id]
if (nextInteractionInfo.interaction.else) {
let nestedLevels = nextInteractionInfo.nestedLevels
if (nestedLevels > maxNestedLevels) {
maxNestedLevels = nestedLevels
}
determineChildParticipants(childParticipants, nextInteractionInfo.interaction, objMap)
prevInteractionInfo.followingElse = nextInteractionInfo
elseBranchInfos.push(nextInteractionInfo)
} else {
break
}
} else {
current = undefined
}
}
/* determine left and right participants */
const leftParticipant= determineLeftParticipant(childParticipants)
const rightParticipant= determineRightParticipant(childParticipants)
/* set most left and right participants in if-branch */
interactionInfo.mostLeftParticipant = leftParticipant
interactionInfo.mostRightParticipant = rightParticipant
interactionInfo.nestedLevels = maxNestedLevels
/* set most left and right participants in else-branches */
for (const elseBranchInfo of elseBranchInfos) {
elseBranchInfo.mostLeftParticipant = leftParticipant
elseBranchInfo.mostRightParticipant = rightParticipant
elseBranchInfo.nestedLevels = maxNestedLevels
}
}
}
for (let interaction of interactions) {
let interactionInfo = interactionMap[interaction.id]
let currentParticipantInfo = interaction.participant ? objMap[interaction.participant] : null
drawInteraction(graph, ctx, parent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap);
}
}
for (let component of allComponents) {
let componentVertex = objMap[component.id].vertex;
let componentHeight = interactionSizing.currentTop + interactionSizing.distance - componentVertex.geometry.offset.y
let geometry = componentVertex.geometry
geometry.height = componentHeight
if (component.lineBottom) {
component.lineBottom.geometry.offset.y=componentHeight
}
}
if (actors) {
for (let actorObj of actors) {
let actorHeight = interactionSizing.currentTop + interactionSizing.distance
let actorVertex = actorVertexes[actorObj]
let geometry = actorVertex.geometry
geometry.height = actorHeight
if (actorObj.lineBottom) {
actorObj.lineBottom.geometry.offset.y = actorHeight
}
}
}
for (let interaction of allInteractions) {
let interactionInfo = interactionMap[interaction.id]
if (interactionInfo.selfVertex) {
interactionInfo.selfVertex.geometry.width = interactionInfo.selfVertex.geometry.width
}
}
// Executes the layout
layout.execute(parent);
}
function determineNestedLevels(interaction) {
let maxNestedLevels = 0
if (interaction.interactions) {
for (const subInteraction of interaction.interactions) {
let nestedLevels = 0
if (subInteraction.condition) {
nestedLevels = 1
}
nestedLevels += determineNestedLevels(subInteraction)
if (maxNestedLevels < nestedLevels) {
maxNestedLevels = nestedLevels
}
}
}
return maxNestedLevels
}
function collectInteractionsRecursive(allInteractions, interactions) {
if (interactions) {
let previousInteraction = undefined
for (let interaction of interactions) {
if (previousInteraction) {
previousInteraction.nextInteraction = interaction
}
previousInteraction = interaction
allInteractions.push(interaction)
if (interaction.interactions) {
collectInteractionsRecursive(allInteractions, interaction.interactions)
}
}
}
}
function collectComponentsRecursive(allComponents, components) {
if (components) {
for (let component of components) {
allComponents.push(component)
if (component.components) {
collectInteractionsRecursive(allComponents, component.components)
}
}
}
}
function createVertexInfo(label, description) {
let doc = mxUtils.createXmlDocument();
let node = doc.createElement('info')
if (label) {
node.setAttribute('label', label);
}
if (description) {
node.setAttribute('description', description);
}
return node
}
function drawActor(graph, parent, sizing, actorObj, objMap, actorVertexes, objStyle) {
let maxWidth = 130;
let childVertexes = [];
let objWidth = maxWidth;
let actorName = actorObj.name
let doc = mxUtils.createXmlDocument();
let actorNode = doc.createElement('x')
actorNode.setAttribute('label', '');
let vObj = graph.insertVertex(parent, null, actorNode, null, null, objWidth, 800, objStyle);
childVertexes.push(vObj);
let titleNode = doc.createElement(actorName);
titleNode.setAttribute('label', actorName);
let halfWidth = (objWidth+5)/2
let vImage = graph.insertVertex(vObj, null, null, 0, 0, objWidth + 5, 40, 'actorImage');
vImage.geometry.offset = new mxPoint(0, 10);
vImage.geometry.relative = true;
childVertexes.push(vImage);
let vTitle = graph.insertVertex(vObj, null, null, 0, 0, objWidth + 5, 20, 'actorTitle', true);
let vTitleText = graph.insertVertex(vTitle, null, titleNode, halfWidth, 15, 0, 0, 'actorTitle');
childVertexes.push(vTitle);
childVertexes.push(vTitleText);
vTitle.geometry.offset = new mxPoint(0, 45);
vTitle.geometry.relative = true;
let vLineBottom = drawParticipantLine(graph, parent, vObj, childVertexes, halfWidth, 65, 880, 'actorLine')
vObj.geometry.offset = new mxPoint(sizing.currentX, 0);
vObj.geometry.relative = true;
let participantInfo = {
type: 'actor',
name: actorName,
participant: actorObj,
vertex: vObj,
left: vObj.geometry.offset.x,
top: vObj.geometry.offset.y,
xOffset: vObj.geometry.offset.x,
interactions: []
}
objMap[actorObj.id] = participantInfo;
actorObj.lineBottom = vLineBottom
graph.groupCells(null, 0, childVertexes)
actorVertexes[actorObj] = vObj;
return vObj
}
function drawParticipantLine(graph, rootParent, vObj, childVertexes, x, top, bottom, lineStyle) {
let vTop = graph.insertVertex(vObj, null, null, 0, 0, 0, 0)
vTop.geometry.offset = new mxPoint(x, top);
vTop.geometry.relative = true;
let vBottom = graph.insertVertex(vObj, null, null, 0, 0, 0, 0)
vBottom.geometry.offset = new mxPoint(x, bottom);
vBottom.geometry.relative = true;
let eMiddle = graph.insertEdge(rootParent, null, '', vTop, vBottom, lineStyle);
childVertexes.push(vTop);
childVertexes.push(vBottom);
childVertexes.push(eMiddle);
return vBottom
}
function addComponentFillColor(style, component) {
if (component) {
if (component.color) {
return style + ';fillColor=' + component.color
}
if (component.stereotype == 'storage') {
return style + ';fillColor=#f58e29'
} else if (component.stereotype == 'ux') {
return style + ';fillColor=#5aa9f1'
} else if (component.stereotype == 'extern') {
return style + ';fillColor=#a8a8a8'
}
}
return style
}
function addComponentLineColor(style, component) {
if (component) {
if (component.stereotype == 'storage') {
return style + ';strokeColor=#835b36'
} else if (component.stereotype == 'ux') {
return style + ';strokeColor=#4376b7'
} else if (component.stereotype == 'extern') {
return style + ';strokeColor=#707070'
}
}
return style
}
function drawComponent(graph, rootParent, parent, sizing, componentsPath, component, objMap, parentComponentInfo, objStyle) {
let objWidth = 250
let doc = mxUtils.createXmlDocument()
let actorNode = doc.createElement('x')
actorNode.setAttribute('label', '');
let isGroup = component.components
let componentWidth = isGroup ? component.components.length * (objWidth +35): objWidth
let componentStyle = isGroup ? 'groupStyle' : objStyle
let titleStyle = isGroup ? 'groupTitle' : 'componentTitle'
let childVertexes = [];
titleStyle = addComponentFillColor(titleStyle, component)
let vObj = graph.insertVertex(parent, null, actorNode, null, null, componentWidth, 800, componentStyle);
if (component.color) {
let style=graph.getModel().getStyle(vObj);
let newStyle=mxUtils.setStyle(style,mxConstants.STYLE_FILLCOLOR,component.color);
let cs= new Array();
cs[0]=vObj;
graph.setCellStyle(newStyle,cs);
}
childVertexes.push(vObj)
const componentUrl = componentsPath + "?focused=" + qualifiedComponentName(component)
const labelText = ""+escapeString(component.label)+""
let titleNode = doc.createElement('info');
titleNode.setAttribute('label', labelText);
let titleTop = isGroup ? 17 : 25
let vTitle = graph.insertVertex(vObj, null, null, 0, 0, componentWidth - 40, titleTop, titleStyle);
let vTitleText = graph.insertVertex(vTitle, null, titleNode, (componentWidth-40)/2, titleTop-13, 0, 0, titleStyle);
childVertexes.push(vTitle)
childVertexes.push(vTitleText)
vTitle.geometry.offset = new mxPoint(20, 10);
vTitle.geometry.relative = true
if (!isGroup) {
const participantLineStyle = addComponentLineColor('componentLine', component)
let vLineBottom = drawParticipantLine(graph, parent, vObj, childVertexes, (objWidth)/2,35,880, participantLineStyle)
component.lineBottom = vLineBottom
}
vObj.geometry.offset = new mxPoint(sizing.currentX, sizing.currentY);
vObj.geometry.relative = true;
let participantInfo = {
type: 'component',
name: component.name,
label: component.label,
participant: component,
parent: parentComponentInfo,
vertex: vObj,
left: vObj.geometry.offset.x,
xOffset: parentComponentInfo ? parentComponentInfo.xOffset + vObj.geometry.offset.x : vObj.geometry.offset.x,
top: vObj.geometry.offset.y,
interactions: []
}
if (parentComponentInfo) {
participantInfo.top += parentComponentInfo.top
}
objMap[component.id] = participantInfo;
if (isGroup) {
let subSizing = {
currentX: 20,
currentY: sizing.currentY + 20
}
for (let subComponent of component.components) {
let vSubObj = drawComponent(graph, rootParent, vObj, subSizing, componentsPath, subComponent, objMap, participantInfo, 'actor', 'title');
childVertexes.push(vSubObj);
}
sizing.currentX = sizing.currentX + subSizing.currentX + 40
} else {
sizing.currentX = sizing.currentX + objWidth + 25
}
let group = graph.groupCells(null, 0, childVertexes);
return group
}
function qualifiedComponentName(component) {
return component.namespace + '.' + component.name
}
function drawInteraction(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap) {
let interaction = interactionInfo.interaction
let maxWidth = 250;
let objWidth = maxWidth;
let doc = mxUtils.createXmlDocument();
let actorNode = doc.createElement('x')
actorNode.setAttribute('label', '');
let interactionBottom = interactionSizing.currentTop;
let childVertexes = [];
let interactWithOtherParticipant = interaction.to && interaction.from !== interaction.to
if (!interactWithOtherParticipant && !interaction.participant) {
if (interaction.execution) {
interactionInfo.selfVertex = drawSelfExecution(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, objMap)
// interactionSizing.currentTop +=interactionInfo.labelSize.height
} else if (interaction.condition) {
drawCondition(graph, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap)
} else if (interaction.reference) {
drawReference(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap)
} else if (interaction.note) {
interactionInfo.selfVertex = drawNote(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap)
} else if (interaction.participant) {
/* root interaction in scenario */
console.log("draw participant")
} else if (currentParticipantInfo) {
drawSelfInvokation(graph, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, objMap)
}
interactionBottom = interactionSizing.currentTop
} else {
let isStartingInteraction = interaction.participant !== undefined
let fromParticipantInfo = objMap[interaction.from]
let fromVertx = fromParticipantInfo.vertex
let toParticipantInfo = objMap[interaction.to]
let toVertx = toParticipantInfo.vertex
let fromX = fromVertx.geometry.getCenterX()
let toX = toVertx.geometry.getCenterX()
let fromDurationOffset = 0
let toDurationOffset = 0
interactionSizing.index++
let rightSide = fromParticipantInfo.xOffset < toParticipantInfo.xOffset
let absoluteFromX = fromParticipantInfo.xOffset + fromVertx.geometry.getCenterX()
let absoluteToX = toParticipantInfo.xOffset + toVertx.geometry.getCenterX()
let labelHeight = interactionInfo.labelSize.height
if (isStartingInteraction) {
labelHeight = 0
} else {
interactionSizing.currentTop = interactionSizing.currentTop + interactionSizing.distance
}
let lineTop = interactionSizing.currentTop + labelHeight// - fromVertx.geometry.offset.y
//let top = interactionSizing.top + interactionSizing.index*interactionSizing.distance
if (!interaction.ignoreResponse) {
if (rightSide) {
if (!toParticipantInfo.currentOffset) {
toParticipantInfo.currentOffset=1
} else {
toParticipantInfo.currentOffset += 1
}
toDurationOffset = toParticipantInfo.currentOffset * 5 + 1
toX -= toDurationOffset
if (interaction.notifyOnly) {
toX = toX + 6 // no duration in this case, therefore extend length of line
}
if (!fromParticipantInfo.currentOffset) {
fromParticipantInfo.currentOffset = 0
}
fromDurationOffset = fromParticipantInfo.currentOffset * 5 + 1
fromX += fromDurationOffset
} else {
if (!toParticipantInfo.currentOffset) {
toParticipantInfo.currentOffset=1
} else {
toParticipantInfo.currentOffset += 1
}
toDurationOffset = toParticipantInfo.currentOffset * 5 + 1
toX += toDurationOffset
if (interaction.notifyOnly) {
toX = toX - 6 // no duration in this case, therefore extend length of line
}
if (!fromParticipantInfo.currentOffset) {
fromParticipantInfo.currentOffset = 0
}
fromDurationOffset = fromParticipantInfo.currentOffset * 5 +1
fromX -= fromDurationOffset
}
}
interactionBottom = lineTop
if (!isStartingInteraction) {
drawInteractionLine(graph, parent, childVertexes, fromVertx, toVertx, false, fromX, toX, lineTop)
}
if (!isStartingInteraction) {
let labelTop = lineTop - interactionInfo.labelSize.height - 5
let vTitleText = createLabel(graph, rootParent, interactionInfo, true, absoluteFromX, rightSide, labelTop)
}
interactionSizing.currentTop = lineTop
let vDuration = null
if (!interaction.ignoreResponse && !interaction.notifyOnly) {
let childVertexes = [];
vDuration = graph.insertVertex(rootParent, null, null, 0,0, 12, 50, 'durationStyle')
if (rightSide) {
vDuration.geometry.offset = new mxPoint(absoluteToX - toDurationOffset, lineTop);
} else {
vDuration.geometry.offset = new mxPoint(absoluteToX + toDurationOffset - 12, lineTop);
}
vDuration.geometry.relative = true;
}
let subInteractionBottom = drawSubInteractions(graph, ctx, rootParent, toVertx, toParticipantInfo, interaction, interactionInfo, interactionSizing, interactionMap, objMap)
if (!interaction.ignoreResponse && !interaction.notifyOnly) {
let backLineTop = interactionSizing.currentTop + interactionInfo.resultLabelSize.height + interactionSizing.distance// - fromVertx.geometry.offset.y
let labelHeight = interactionInfo.resultLabelSize.height
let backLabelTop = backLineTop - interactionInfo.resultLabelSize.height - 5
let backTop = interactionSizing.currentTop + interactionSizing.distance + interactionSizing.currentTop
vDuration.geometry.height = subInteractionBottom - lineTop //+ interactionSizing.distance
if (fromParticipantInfo.type !== 'actor' && !interaction.triggerOnly) {
if (!isStartingInteraction) {
drawInteractionLine(graph, parent, childVertexes, toVertx, fromVertx, true, toX, fromX, backLineTop)
}
interactionBottom = backLineTop
}
if (interaction.result) {
createLabel(graph, rootParent, interactionInfo, false, absoluteFromX, rightSide, backLabelTop)
// interactionSizing.currentTop = interactionSizing.currentTop + labelHeight
} else {
// interactionSizing.currentTop = interactionSizing.currentTop + interactionSizing.distance + 100
}
interactionSizing.currentTop = backLineTop //+ interactionSizing.distance
toParticipantInfo.currentOffset -= 1
} else {
let backLineTop = interactionSizing.currentTop //+ interactionSizing.distance
interactionSizing.currentTop = backLineTop // + interactionSizing.distance
toParticipantInfo.currentOffset -= 1
}
//interactionSizing.currentTop = interactionSizing.currentTop+ interactionSizing.distance
}
return interactionBottom;
}
function hasResponse(interaction, objMap) {
let fromParticipantInfo = objMap[interaction.from]
if (fromParticipantInfo) {
return fromParticipantInfo.type !== 'actor' && !interaction.triggerOnly
}
return false
}
function drawSubInteractions(graph, ctx, rootParent, toVertx, toParticipantInfo, interaction, interactionInfo, interactionSizing, interactionMap, objMap) {
let durationBottom = interactionSizing.currentTop
if (interaction.interactions) {
durationBottom = interactionSizing.currentTop + interactionSizing.distance
let lastSubInteraction = undefined
let lastBottom = durationBottom
for (let subInteraction of interaction.interactions) {
lastSubInteraction = subInteraction
let subInteractionInfo = interactionMap[subInteraction.id]
//interactionSizing.currentTop = interactionSizing.currentTop+ interactionSizing.distance
durationBottom = lastBottom;
let bottom = drawInteraction(graph, ctx, rootParent, toVertx, toParticipantInfo, interactionSizing, subInteractionInfo, interactionMap, objMap);
lastBottom = bottom + interactionSizing.distance
//if (hasResponse(subInteraction, objMap)) {
if (!subInteraction.ignoreResponse ) {
durationBottom = bottom
if (subInteraction.result) {
// durationBottom += subInteractionInfo.resultLabelSize.height
}
}
if (lastSubInteraction.execution) {
durationBottom = bottom
}
}
if (lastSubInteraction.execution) {
let lastSubInteractionInfo = interactionMap[lastSubInteraction.id]
// durationBottom += lastSubInteractionInfo.labelSize.height + interactionSizing.executionBoxSpace;
}
}
if (hasResponse(interaction, objMap)) {
if (interaction.result) {
durationBottom += interactionInfo.resultLabelSize.height + interactionSizing.distance
} else {
durationBottom += interactionSizing.distance
}
} else if (!interaction.interactions) { // empty (no interactions and no response) -> show short dummy box
durationBottom += interactionSizing.distance
}
return durationBottom
}
function drawSelfInvokation(graph, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, objMap) {
let currentVertex = currentParticipantInfo.vertex
let interaction = interactionInfo.interaction
let labelHeight = interactionInfo.labelSize.height
let top = interactionSizing.currentTop + interactionSizing.distance// - currentVertex.geometry.offset.y
let lineTop = top + labelHeight - currentVertex.geometry.offset.y
let left = currentVertex.geometry.getCenterX() + (currentParticipantInfo.currentOffset * 6)
let absoluteFromX = currentParticipantInfo.xOffset + currentVertex.geometry.getCenterX()
let childVertexes = [];
let vStart = graph.insertVertex(currentVertex, null, null, 0,0, 0, 0)
vStart.geometry.offset = new mxPoint(left, lineTop);
vStart.geometry.relative = true;
let vTopRight = graph.insertVertex(currentVertex, null, null, 0,0, 0, 0)
vTopRight.geometry.offset = new mxPoint(left + interactionSizing.selfWidth, lineTop);
vTopRight.geometry.relative = true;
let vBottomRight = graph.insertVertex(currentVertex, null, null, 0,0, 0, 0)
vBottomRight.geometry.offset = new mxPoint(left + interactionSizing.selfWidth, lineTop + interactionSizing.selfHeight);
vBottomRight.geometry.relative = true;
let vEnd = graph.insertVertex(currentVertex, null, null, 0,0, 0, 0)
vEnd.geometry.offset = new mxPoint(left, lineTop + interactionSizing.selfHeight);
vEnd.geometry.relative = true;
childVertexes.push(vStart);
childVertexes.push(vTopRight);
childVertexes.push(vBottomRight);
childVertexes.push(vEnd);
let eMiddle = graph.insertEdge(currentVertex, null, '', vStart, vTopRight, 'simpleLine');
let eLine2 = graph.insertEdge(currentVertex, null, '', vTopRight, vBottomRight, 'simpleLine');
let eLine3 = graph.insertEdge(currentVertex, null, '', vBottomRight, vEnd, 'interactionLine');
childVertexes.push(eMiddle);
childVertexes.push(eLine2);
childVertexes.push(eLine3);
let vTitleText = createLabel(graph, rootParent, interactionInfo, true, absoluteFromX, true, top -5)
interactionSizing.currentTop = lineTop + interactionSizing.selfHeight + interactionSizing.distance
childVertexes.push(vTitleText);
}
function determineLeftParticipant(interactionInfo, objMap) {
let childInteractions = new Set();
determineChildParticipants(childInteractions, interactionInfo.interaction, objMap)
if (childInteractions.size > 0) {
return childInteractions.values().next()
} else {
return null
}
}
function determineLeftParticipant(participants) {
if (participants.size > 0) {
let leftParticipant = null
let minOffset = 0
for (let participant of participants) {
let xOffset = participant.vertex.geometry.offset.x
if (leftParticipant === null || xOffset < minOffset) {
minOffset = xOffset
leftParticipant = participant
}
}
return leftParticipant
} else {
return null
}
}
function determineRightParticipant(participants) {
if (participants.size > 0) {
let rightParticipant = null
let maxOffset = 0
for (let participant of participants) {
let xOffset = participant.vertex.geometry.offset.x
if (rightParticipant === null || xOffset > maxOffset) {
maxOffset = xOffset
rightParticipant = participant
}
}
return rightParticipant
} else {
return null
}
}
function determineChildParticipants(childInteractions, interaction, objMap) {
if (interaction.from) {
let fromParticipantInfo = objMap[interaction.from]
if (fromParticipantInfo) {
childInteractions.add(fromParticipantInfo)
}
}
if (interaction.to) {
let toParticipantInfo = objMap[interaction.to]
if (toParticipantInfo) {
childInteractions.add(toParticipantInfo)
}
}
if (interaction.interactions) {
for (let subInteraction of interaction.interactions) {
determineChildParticipants(childInteractions, subInteraction, objMap)
}
}
}
function determineParticipants(childInteractions, components, objMap) {
if (components) {
for (let component of components) {
let participantInfo = objMap[component]
childInteractions.add(participantInfo)
}
}
}
function drawReference(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap, componentVertexes) {
let topBefore = interactionSizing.currentTop
if (ctx.leftParticipant && ctx.rightParticipant) {
let interaction = interactionInfo.interaction
let labelHeight = interactionInfo.labelSize.height
let labelWidth = interactionInfo.labelSize.width
let lineTop = interactionSizing.currentTop + interactionSizing.distance
let top = lineTop
let absoluteFromX = ctx.leftParticipant.xOffset + 40
let absoluteToX = ctx.rightParticipant.xOffset + ctx.rightParticipant.vertex.geometry.width - 40
let width = absoluteToX - absoluteFromX
let labelRect = interactionInfo.labelSize
let labelText = interactionInfo.interaction.name
if (interactionInfo.interaction.href) {
labelText = ""+labelText+""
}
let processInfo = createVertexInfo(labelText, interaction.description)
let childVertexes = [];
let vStart = graph.insertVertex(rootParent, null, processInfo, null, null, width, 10, 'subProcessStyle')
vStart.geometry.offset = new mxPoint(absoluteFromX, top);
vStart.geometry.relative = true;
//graph.addListener(vStart, "click", function () { console.log("event...")} );
//drawSubInteractions(graph, ctx, rootParent, vStart, null, interaction, interactionSizing, interactionMap, objMap)
//interactionSizing.currentTop = interactionSizing.currentTop + interactionSizing.distance + labelHeight
let loopHeight = labelHeight + 25
vStart.geometry.height = loopHeight
interactionSizing.currentTop = interactionSizing.currentTop + loopHeight + interactionSizing.distance
return vStart
} else {
return null
}
}
function determineInteractionHref(interactionInfo) {
if (window.location.href.includes("diagram/processes/")) {
return interactionInfo.interaction.href
} else {
return "../../" + interactionInfo.interaction.href
}
}
function drawCondition(graph, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap, componentVertexes) {
let topBefore = interactionSizing.currentTop
let childParticipants = new Set();
determineChildParticipants(childParticipants, interactionInfo.interaction, objMap)
const leftParticipant= determineLeftParticipant(childParticipants)
const rightParticipant= determineRightParticipant(childParticipants)
const ctx = {
children: childParticipants,
leftParticipant: leftParticipant,
rightParticipant: rightParticipant,
mostLeftParticipant: interactionInfo.mostLeftParticipant,
mostRightParticipant: interactionInfo.mostRightParticipant
}
if (ctx.children.size === 0) {
ctx.leftParticipant = currentParticipantInfo
ctx.rightParticipant = currentParticipantInfo
if (!ctx.mostLeftParticipant) {
ctx.mostLeftParticipant = currentParticipantInfo
}
if (!ctx.mostRightParticipant) {
ctx.mostRightParticipant = currentParticipantInfo
}
}
if (ctx.leftParticipant && ctx.mostRightParticipant) {
let interaction = interactionInfo.interaction
let topDistance= interactionInfo.interaction.else ? 0 : interactionSizing.distance
let lineTop = interactionSizing.currentTop + topDistance //- ctx.leftParticipant.top
interactionSizing.currentTop = lineTop
let top = lineTop
let absoluteFromX = ctx.mostLeftParticipant.xOffset - 10
let absoluteToX = ctx.mostRightParticipant.xOffset + ctx.mostRightParticipant.vertex.geometry.width + 10
if (interactionInfo.nestedLevels) {
absoluteFromX -= (10 * interactionInfo.nestedLevels)
absoluteToX += (10 * interactionInfo.nestedLevels)
}
let width = absoluteToX - absoluteFromX
interactionInfo.labelSize = mxUtils.getSizeForString(interactionInfo.interaction.name, null, null,width - 20)
let labelHeight = interactionInfo.labelSize.height
let labelWidth = interactionInfo.labelSize.width
let labelRect = interactionInfo.labelSize
let style = ''
if (interaction.condition) {
if (interaction.else) {
style='elseStyle'
} else {
style='ifStyle'
}
} else {
style='loopStyle'
}
let childVertexes = [];
let vStart = graph.insertVertex(rootParent, null, '', null, null, width, 100, style)
vStart.geometry.offset = new mxPoint(absoluteFromX, lineTop);
vStart.geometry.relative = true;
const categoryBoxHeight = 17
/* 'border'-lines */
if (interaction.condition && !interaction.else) {
graph.insertEdge(vStart, null, '', vStart, vStart, 'altBorderStyle;exitX=1;entryDx='+(70+6)+';entryX=0;exitDx=-6;exitY=0;exitDy=6;exitPerimeter=0;entryY=0;entryDy=6;entryPerimeter=0;');
graph.insertEdge(vStart, null, '', vStart, vStart, 'altBorderStyle;exitX=0;exitDx=6;entryX=0;entryDx=6;exitY=1;exitDy=-6;exitPerimeter=0;entryY=0;entryDy='+(categoryBoxHeight + 6)+';entryPerimeter=0;');
} else if (interaction.condition && interaction.else){
graph.insertEdge(vStart, null, '', vStart, vStart, 'altSeparatorStyle;exitX=1;exitDx=-6;entryX=0;entryDx=6;exitY=0;exitDy=6;exitPerimeter=0;entryY=0;entryDy=6;entryPerimeter=0;');
graph.insertEdge(vStart, null, '', vStart, vStart, 'altBorderStyle;exitX=0;exitDx=6;entryX=0;entryDx=6;exitY=1;exitDy=-6;exitPerimeter=0;entryY=0;entryDy=6;entryPerimeter=0;');
}
graph.insertEdge(vStart, null, '', vStart, vStart, 'altBorderStyle;exitX=1;exitDx=-6;entryX=1;entryDx=-6;exitY=1;exitDy=-6;exitPerimeter=0;entryY=0;entryDy=6;entryPerimeter=0;');
if (!interaction.nextInteraction || !interaction.nextInteraction.else) {
graph.insertEdge(vStart, null, '', vStart, vStart, 'altBorderStyle;exitX=1;exitDx=-6;entryX=0;entryDx=6;exitY=1;exitDy=-6;exitPerimeter=0;entryY=1;entryDy=-6;entryPerimeter=0;');
}
/* condition and loop labels */
let labelY = 5;
if (interaction.condition && !interaction.else) {
let conditionCategory = interaction.loop ? 'loop' : 'alt'
let vCondition = graph.insertVertex(vStart, null, conditionCategory, null, null, 70, categoryBoxHeight, 'conditionStyle')
vCondition.geometry.offset = new mxPoint(0, 0);
vCondition.geometry.relative = true;
labelY = 20
}
let vConditionText = graph.insertVertex(vStart, null, escapeString(interactionInfo.interaction.name), 0,0, width-20, labelHeight + 5, 'conditionTextStyle')
vConditionText.geometry.offset = new mxPoint(15, labelY);
vConditionText.geometry.relative = true;
/* current top for sub interactions */
if (interaction.condition && !interaction.else) {
interactionSizing.currentTop = lineTop + labelHeight + 20
} else {
interactionSizing.currentTop = lineTop + labelHeight
}
drawSubInteractions(graph, ctx, rootParent, vStart, currentParticipantInfo, interaction, interactionInfo, interactionSizing, interactionMap, objMap)
let loopHeight = interactionSizing.currentTop - lineTop + topDistance
if (interactionInfo.interaction.else) {
loopHeight += interactionSizing.distance
}
vStart.geometry.height = loopHeight
interactionSizing.currentTop = interactionSizing.currentTop + interactionSizing.distance
return vStart
} else {
return null
}
}
function drawNote(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, interactionMap, objMap, componentVertexes) {
let currentVertex = currentParticipantInfo? currentParticipantInfo.vertex : null
let interaction = interactionInfo.interaction
let labelHeight = interactionInfo.labelSize.height
let yOffset = currentVertex ? currentVertex.geometry.offset.y : 0
let lineTop = interactionSizing.currentTop + interactionSizing.distance// - yOffset
let top = lineTop
let centerX = currentParticipantInfo ? currentParticipantInfo.xOffset + currentVertex.geometry.getCenterX() : ctx.leftParticipant.xOffset + 30
if (currentParticipantInfo) {
centerX += (currentParticipantInfo.currentOffset * 6)
}
let absoluteFromX = centerX + 10
let labelRect = interactionInfo.labelSize
let noteWidth = currentParticipantInfo ? labelRect.width+20 : (ctx.rightParticipant.xOffset + ctx.rightParticipant.vertex.geometry.width - 40) - centerX
let vStart = graph.insertVertex(rootParent, null, interactionInfo.interaction.name, 0,0, noteWidth+10, labelRect.height+12, 'noteStyle')
vStart.geometry.offset = new mxPoint(absoluteFromX, top);
vStart.geometry.relative = true;
if (currentParticipantInfo) {
let p1 = graph.insertVertex(rootParent, null, '', null, null, 0,0, 'noteStyle')
p1.geometry.offset = new mxPoint(centerX, top+10);
p1.geometry.relative = true;
let p2 = graph.insertVertex(rootParent, null, '', null, null, 0,0, 'noteStyle')
p2.geometry.offset = new mxPoint(absoluteFromX, top+10);
p2.geometry.relative = true;
graph.insertEdge(rootParent, null, '', p1, p2, 'noteLineStyle');
}
let p3 = graph.insertVertex(rootParent, null, '', null, null, 0,0, 'noteStyle')
p3.geometry.offset = new mxPoint(absoluteFromX, top);
p3.geometry.relative = true;
let p4 = graph.insertVertex(rootParent, null, '', null, null, 0,0, 'noteStyle')
p4.geometry.offset = new mxPoint(absoluteFromX, top+vStart.geometry.height);
p4.geometry.relative = true;
//graph.insertEdge(rootParent, null, '', p3, p4, 'noteLeftLineStyle');
interactionSizing.currentTop = top+vStart.geometry.height
return vStart
}
function drawSelfExecution(graph, ctx, rootParent, parent, currentParticipantInfo, interactionSizing, interactionInfo, objMap, componentVertexes) {
if (currentParticipantInfo) {
let currentVertex = currentParticipantInfo.vertex
let interaction = interactionInfo.interaction
let labelHeight = interactionInfo.labelSize.height
let lineTop = interactionSizing.currentTop + interactionSizing.distance// + labelHeight// - currentVertex.geometry.offset.y
let left = currentVertex.geometry.getCenterX()
let top = lineTop
let absoluteFromX = currentParticipantInfo.xOffset + currentVertex.geometry.getCenterX()
let labelRect = interactionInfo.labelSize
let executionHeight = labelRect.height+interactionSizing.executionBoxSpace
let childVertexes = [];
let vStart = graph.insertVertex(rootParent, null, interactionInfo.interaction.name, 0,0, labelRect.width+12, executionHeight, 'executionStyle')
vStart.geometry.offset = new mxPoint(absoluteFromX - labelRect.width/2, top);
vStart.geometry.relative = true;
interactionSizing.currentTop = interactionSizing.currentTop + executionHeight + interactionSizing.distance
//childVertexes.push(vStart);
return vStart
} else {
/* current participant info missing, probably (direct or indirect) child of actor invocation */
let currentVertex = parent
let interaction = interactionInfo.interaction
let labelHeight = interactionInfo.labelSize.height
let lineTop = interactionSizing.currentTop + interactionSizing.distance// + labelHeight// - currentVertex.geometry.offset.y
let left = currentVertex.geometry.getCenterX()
let top = lineTop
let absoluteFromX = ctx.leftParticipant.xOffset + 40
let labelRect = interactionInfo.labelSize
let executionHeight = labelRect.height+interactionSizing.executionBoxSpace
let childVertexes = [];
let vStart = graph.insertVertex(rootParent, null, interactionInfo.interaction.name, 0,0, labelRect.width+12, executionHeight, 'executionStyle')
vStart.geometry.offset = new mxPoint(absoluteFromX, top);
vStart.geometry.relative = true;
interactionSizing.currentTop = interactionSizing.currentTop + executionHeight + interactionSizing.distance
//childVertexes.push(vStart);
return vStart
}
}
function createLabel(graph, parent, interactionInfo, isName, x, rightSide, top) {
let text = isName ? interactionInfo.name : interactionInfo.interaction.result
let labelRect = isName ? interactionInfo.labelSize : interactionInfo.resultLabelSize
let doc = mxUtils.createXmlDocument();
let titleNode = doc.createElement('info');
titleNode.setAttribute('label', escapeString(text));
let labelWidth = labelRect.width;
let left = rightSide ? x + 15 : x-labelWidth-15
let labelStyle = rightSide ? 'leftLabel' : 'rightLabel'
let vertex = graph.insertVertex(parent, null, titleNode, 0, 0, 0, 0,labelStyle)
vertex.geometry.offset = new mxPoint(left, top);
vertex.geometry.width = labelRect.width
vertex.geometry.height = labelRect.height
vertex.geometry.relative = true;
//vertex.geometry.alternateBounds=new mxRectangle(left, top, labelRect.width, labelRect.height);
return vertex
}
function escapeString(str) {
if (str) {
/*
& &
' '
< <
> >
" "
Ä Ä
Ö Ö
Ü Ü
ä ä
ö ö
ü ü
ß ß
*/
let escaped = str.replace("ö","ö")
escaped = escaped.replace("ü","ü")
escaped = escaped.replace("ä","ä")
escaped = escaped.replace("ß","ß")
escaped = escaped.replace('"',""")
escaped = escaped.replace('Ä',"Ä")
escaped = escaped.replace('Ö',"Ö")
escaped = escaped.replace('Ü',"ß")
return escaped
}
return str
}
function drawInteractionLine(graph, vObj, childVertexes, fromVertx, toVertx, isResponse, left, right, top) {
let vTop = graph.insertVertex(fromVertx, null, null, 0,0, 0, 0)
vTop.geometry.offset = new mxPoint(left, top - fromVertx.geometry.offset.y);
vTop.geometry.relative = true;
let vBottom = graph.insertVertex(toVertx, null, null, 0,0, 0, 0)
vBottom.geometry.offset = new mxPoint(right, top - toVertx.geometry.offset.y);
vBottom.geometry.relative = true;
childVertexes.push(vTop);
childVertexes.push(vBottom);
let style = isResponse ? 'interactionResponseLine' : 'interactionLine';
let eMiddle = graph.insertEdge(vObj, null, '', vTop, vBottom, style);
childVertexes.push(eMiddle);
}
function downloadSVG(graph, fileName) {
let background = '#ffffff';
let scale = 1;
let border = 1;
let imgExport = new mxImageExport();
let bounds = graph.getGraphBounds();
let vs = graph.view.scale;
// Prepares SVG document that holds the output
let svgDoc = mxUtils.createXmlDocument();
let root = (svgDoc.createElementNS != null) ?
svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg');
if (background != null) {
if (root.style != null) {
root.style.backgroundColor = background;
} else {
root.setAttribute('style', 'background-color:' + background);
}
}
if (svgDoc.createElementNS == null) {
root.setAttribute('xmlns', mxConstants.NS_SVG);
root.setAttribute('xmlns:xlink', mxConstants.NS_XLINK);
} else {
// KNOWN: Ignored in IE9-11, adds namespace for each image element instead. No workaround.
root.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', mxConstants.NS_XLINK);
}
root.setAttribute('width', (Math.ceil(bounds.width * scale / vs) + 2 * border) + 'px');
root.setAttribute('height', (Math.ceil(bounds.height * scale / vs) + 2 * border) + 'px');
root.setAttribute('version', '1.1');
// Adds group for anti-aliasing via transform
let group = (svgDoc.createElementNS != null) ?
svgDoc.createElementNS(mxConstants.NS_SVG, 'g') : svgDoc.createElement('g');
group.setAttribute('transform', 'translate(0.5,0.5)');
root.appendChild(group);
svgDoc.appendChild(root);
// Renders graph. Offset will be multiplied with state's scale when painting state.
let svgCanvas = new mxSvgCanvas2D(group);
svgCanvas.translate(Math.floor((border / scale - bounds.x) / vs), Math.floor((border / scale - bounds.y) / vs));
svgCanvas.scale(scale / vs);
// Displayed if a viewer does not support foreignObjects (which is needed to HTML output)
svgCanvas.foAltText = '[Not supported by viewer]';
imgExport.drawState(graph.getView().getState(graph.model.root), svgCanvas);
save(fileName, mxUtils.getPrettyXml(root))
}
function save(filename, data) {
const blob = new Blob([data], {type: 'image/svg'});
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob, {oneTimeOnly: true});
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
function main(container, titleLink, diagramName) {
// Checks if browser is supported
if (!mxClient.isBrowserSupported()) {
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
} else {
// Disables the built-in context menu
mxEvent.disableContextMenu(container);
mxConstants.VERTEX_SELECTION_COLOR = '#15808c';
mxConstants.VERTEX_SELECTION_STROKEWIDTH = 2;
mxConstants.VERTEX_SELECTION_DASHED = true;
mxGraph.prototype.isHtmlLabel = function (cell) {
return true;
// return this.isHtmlLabels();
};
//mxGraph.prototype.ordered = false;
// Creates the graph inside the given container
let graph = new mxGraph(container);
titleLink.onclick = function() {
downloadSVG(graph, diagramName + ".svg");
};
graph.foldingEnabled = false;
//graph.recursiveResize = true;
let hasQueryParameter = function (cell) {
return cell != null &&
cell.getAttribute("queryParameter") != undefined;
};
graph.convertValueToString = function (cell) {
let label = cell.getAttribute('label');
if (label !== undefined) {
return label;
}
return cell.value;
};
// Prevent moving certain cells
graph.isCellMovable = function (cell) {
return cell.getAttribute("isClass") !== undefined;
};
graph.isCellSelectable = function (cell) {
return false
}
graph.border = 80;
graph.getView().translate = new mxPoint(graph.border / 2, graph.border / 2);
function CollateShape()
{
mxEllipse.call(this);
};
mxUtils.extend(CollateShape, mxEllipse);
CollateShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
c.begin();
c.moveTo(x, y);
c.lineTo(x, y+h);
c.lineTo(x + w - 8 , y+h);
c.lineTo(x + w , y+h - 8);
c.lineTo(x + w , y);
c.close();
c.fillAndStroke();
};
mxCellRenderer.registerShape('collate', CollateShape);
// Adds rubberband selection
new mxRubberband(graph);
// Installs a custom global tooltip
graph.setTooltips(true);
graph.getTooltip = function (state) {
let cell = state.cell;
let model = this.getModel();
if (model.isEdge(cell)) {
// TODO
} else {
if (mxUtils.isNode(cell.value)) {
let description = cell.getAttribute('description', null)
if (description) {
return description
}
}
return null;
}
};
// Changes the default vertex style in-place
var style = graph.getStylesheet().getDefaultVertexStyle();
style[mxConstants.STYLE_PERIMETER_SPACING] = 6;
// style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
// style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
style[mxConstants.STYLE_RESIZABLE] = 0;
// style[mxConstants.STYLE_ROUNDED] = true;
//style[mxConstants.STYLE_SHADOW] = true;
style[mxConstants.STYLE_FILLCOLOR] = 'none';
style[mxConstants.STYLE_FOLDABLE] = 0;
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
graph.getStylesheet().putCellStyle('actor', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 100;
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(244,248,255)';
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(169,189,231)';
style[mxConstants.STYLE_OPACITY] = 100;
graph.getStylesheet().putCellStyle('durationStyle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FONTCOLOR] = '#eea52b';
graph.getStylesheet().putCellStyle('actorTitle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FONTCOLOR] = '#4e9c9f';
graph.getStylesheet().putCellStyle('groupTitle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(58,93,157)';
style[mxConstants.STYLE_ALIGN] = 'left';
graph.getStylesheet().putCellStyle('leftLabel', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(58,93,157)';
style[mxConstants.STYLE_ALIGN] = 'right';
graph.getStylesheet().putCellStyle('rightLabel', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(58,93,157)';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(206,221,253)';
//style[mxConstants.STYLE_FILLCOLOR] = 'rgb(238,247,255)';
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(185,199,238)';
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 100;
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_ARCSIZE] = 10;
style[mxConstants.STYLE_ABSOLUTE_ARCSIZE] = 1;
graph.getStylesheet().putCellStyle('executionStyle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(79,108,91)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(179,232,201)';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 100;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_SPACING] = 10;
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_ARCSIZE] = 4;
style[mxConstants.STYLE_ABSOLUTE_ARCSIZE] = 1;
graph.getStylesheet().putCellStyle('noteStyle', style);
style = [];
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(79,108,91)';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
graph.getStylesheet().putCellStyle('noteLineStyle', style);
style = [];
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(210,161,75)';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_STROKEWIDTH] = 3;
style[mxConstants.STYLE_FILL_OPACITY] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
graph.getStylesheet().putCellStyle('noteLeftLineStyle', style);
style = [];
style[mxConstants.STYLE_STROKECOLOR] = '#b9a0b0';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_FILL_OPACITY] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
graph.getStylesheet().putCellStyle('altBorderStyle', style);
style = [];
style[mxConstants.STYLE_STROKECOLOR] = '#b9a0b0';
style[mxConstants.STYLE_DASHED] = 1;
style[mxConstants.STYLE_DASH_PATTERN] = '3';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_FILL_OPACITY] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
graph.getStylesheet().putCellStyle('altSeparatorStyle', style);
style = [];
//style[mxConstants.STYLE_FONTCOLOR] = 'rgb(84,121,187)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(255,255,255)';
style[mxConstants.STYLE_STROKECOLOR] = '#7F0055';
style[mxConstants.STYLE_FONTCOLOR] = '#7F0055';
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 45;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_SHAPE] = 'collate';
graph.getStylesheet().putCellStyle('conditionStyle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#804b6a';
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_OPACITY] = 100;
style[mxConstants.STYLE_FILL_OPACITY] = 100;
style[mxConstants.STYLE_SHAPE] = 'collate';
graph.getStylesheet().putCellStyle('conditionTextStyle', style);
style = [];
//style[mxConstants.STYLE_FONTCOLOR] = 'rgb(84,121,187)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(140,140,140)';
style[mxConstants.STYLE_FILL_OPACITY] = 7;
graph.getStylesheet().putCellStyle('ifStyle', style);
style = [];
//style[mxConstants.STYLE_FONTCOLOR] = 'rgb(84,121,187)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(140,140,140)';
style[mxConstants.STYLE_FILL_OPACITY] = 10;
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
graph.getStylesheet().putCellStyle('elseStyle', style);
style = [];
//style[mxConstants.STYLE_FONTCOLOR] = 'rgb(84,121,187)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(140,140,140)';
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(194,164,162)';
style[mxConstants.STYLE_FILL_OPACITY] = 10;
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
graph.getStylesheet().putCellStyle('loopStyle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(255,255,255)';
//style[mxConstants.STYLE_ALIGN] = 'right';
style[mxConstants.STYLE_FILLCOLOR] = 'rgb(133,139,248)';
style[mxConstants.STYLE_FILL_OPACITY] = 100;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_ARCSIZE] = 6;
graph.getStylesheet().putCellStyle('subProcessStyle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_STROKECOLOR] = '#497f81';
style[mxConstants.STYLE_FONTCOLOR] = '#ffffff';
style[mxConstants.STYLE_FILLCOLOR] = '#5bbac7';
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_ARCSIZE] = 6;
style[mxConstants.STYLE_ABSOLUTE_ARCSIZE] = 1;
graph.getStylesheet().putCellStyle('componentTitle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_SPACING] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
// style[mxConstants.STYLE_STROKECOLOR] = '#497f81';
style[mxConstants.STYLE_FONTCOLOR] = 'rgb(58,93,157)';
// style[mxConstants.STYLE_FILLCOLOR] = '#5bbac7';
// style[mxConstants.STYLE_ROUNDED] = true;
// style[mxConstants.STYLE_ARCSIZE] = 6;
// style[mxConstants.STYLE_ABSOLUTE_ARCSIZE] = 1;
graph.getStylesheet().putCellStyle('infoStyle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_FILLCOLOR] = '#f5fafa';
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_ARCSIZE] = 2;
style[mxConstants.STYLE_ABSOLUTE_ARCSIZE] = 1;
graph.getStylesheet().putCellStyle('groupStyle', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 2;
graph.getStylesheet().putCellStyle('object', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_STROKECOLOR] = '#717171';
graph.getStylesheet().putCellStyle('exObject', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 2;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('otherObject', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
graph.getStylesheet().putCellStyle('title', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
//style[mxConstants.STYLE_FONTCOLOR] = '#808a99';
graph.getStylesheet().putCellStyle('exTitle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('otherTitle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_PERIMETER_SPACING] = 1;
graph.getStylesheet().putCellStyle('property', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
//style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_PERIMETER_SPACING] = 1;
//style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
//style[mxConstants.STYLE_SPACING] = 0;
graph.getStylesheet().putCellStyle('propertyDetail', style);
/* Edge styles */
style = graph.getStylesheet().getDefaultEdgeStyle();
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
style[mxConstants.STYLE_ROUNDED] = true;
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 4;
style[mxConstants.STYLE_ENDSIZE] = 3;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 2;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
graph.getStylesheet().putCellStyle('reference', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STROKECOLOR] = '#4bb0b2';
style[mxConstants.STYLE_DASHED] = 1;
style[mxConstants.STYLE_DASH_PATTERN] = '6';
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
graph.getStylesheet().putCellStyle('componentLine', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STROKECOLOR] = '#eea52b';
style[mxConstants.STYLE_DASHED] = 1;
style[mxConstants.STYLE_DASH_PATTERN] = '6';
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
graph.getStylesheet().putCellStyle('actorLine', style);
style = [];
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
style[mxConstants.STYLE_PERIMETER] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
graph.getStylesheet().putCellStyle('interactionLine', style);
style = [];
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
style[mxConstants.STYLE_DASHED] = 1;
style[mxConstants.STYLE_DASH_PATTERN] = '4';
style[mxConstants.STYLE_PERIMETER] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
graph.getStylesheet().putCellStyle('interactionResponseLine', style);
style = [];
style[mxConstants.STYLE_PERIMETER_SPACING] = -6;
style[mxConstants.STYLE_PERIMETER] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
graph.getStylesheet().putCellStyle('simpleLine', style);
// image string encoded with: https://jgraph.github.io/drawio-tools/tools/base64.html referenced in: https://stackoverflow.com/questions/51039801/how-to-add-a-svg-image-to-mxgraph
let actorImageBase64 = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+Cjxzdmcgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEyMiAyMjkiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM6c2VyaWY9Imh0dHA6Ly93d3cuc2VyaWYuY29tLyIgc3R5bGU9ImZpbGwtcnVsZTpldmVub2RkO2NsaXAtcnVsZTpldmVub2RkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxLjU7Ij4KICAgIDxnIHRyYW5zZm9ybT0ibWF0cml4KDEuMTI5MDQsMCwwLDEuMjQwNzUsLTk3LjA3MDIsLTExNy4yMSkiPgogICAgICAgIDxlbGxpcHNlIGN4PSIxNDAuMDI0IiBjeT0iMTIzLjE2OCIgcng9IjI2LjE1MyIgcnk9IjIzLjc5OCIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6cmdiKDIyNCwxNDksMCk7c3Ryb2tlLXdpZHRoOjcuODdweDsiLz4KICAgIDwvZz4KICAgIDxnIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk3OTkzLDAuMDUwODM1MywtMC4wNjMzMTczLDAuODAxMjU2LC0yNC41NDksLTgxLjY2NjEpIj4KICAgICAgICA8cGF0aCBkPSJNOTYuNjYxLDE3Mi4wODdMMTAzLjI5MywyNzYuNjExIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTpyZ2IoMjI0LDE0OSwwKTtzdHJva2Utd2lkdGg6MTAuNDRweDtzdHJva2UtbGluZWNhcDpidXR0OyIvPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMDYwNjMzOSwwLjk5Nzk5MywtMC45NTU2OTgsLTAuMDYzMzE3MywyODEuNzg4LDYuOTkzMDgpIj4KICAgICAgICA8cGF0aCBkPSJNOTYuNjYxLDE3Mi4wODdMMTAzLjI5MywyNzYuNjExIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTpyZ2IoMjI0LDE0OSwwKTtzdHJva2Utd2lkdGg6OS41NnB4OyIvPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoLTAuNzgyNTA3LDAuNDk3MjA0LC0wLjQ3MjE4NywtMC43NTIyMDEsMjcyLjQ2MiwzMDEuOTMxKSI+CiAgICAgICAgPHBhdGggZD0iTTk2LjY2MSwxNzIuMDg3TDEwMy4yOTMsMjc2LjYxMSIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6cmdiKDIyNCwxNDksMCk7c3Ryb2tlLXdpZHRoOjEwLjMxcHg7Ii8+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc4MjUwNywwLjQ5NzIwNCwwLjQ3MjE4NywtMC43NTIyMDEsLTE1MC41MzQsMzAxLjkzMSkiPgogICAgICAgIDxwYXRoIGQ9Ik05Ni42NjEsMTcyLjA4N0wxMDMuMjkzLDI3Ni42MTEiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOnJnYigyMjQsMTQ5LDApO3N0cm9rZS13aWR0aDoxMC4zMXB4OyIvPgogICAgPC9nPgo8L3N2Zz4K"
style = [];
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_IMAGE] = actorImageBase64;
//style[mxConstants.STYLE_IMAGE] = 'img/actor.svg';
style[mxConstants.STYLE_FONTCOLOR] = '#FFFFFF';
graph.getStylesheet().putCellStyle('actorImage', style); // name style
/* Layout algorithm */
//let layout = new mxCompactTreeLayout(graph);
let layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);
layout.edgeStyle = 4;
layout.intraCellSpacing = 100;
layout.interHierarchySpacing = 100;
let parent = graph.getDefaultParent();
graph.border = 30;
graph.isWrapping = function(cell)
{
return true
};
const data = createDiagramData();
const processesLink = document.getElementById('processesLink')
if (processesLink) {
processesLink.onclick = function() {
if (window.location.href.includes("diagram/processes/")) {
window.location.href = data.applicationName.toLowerCase() + "_processes.html";
} else {
window.location.href = "../../processes/" + data.applicationName.toLowerCase() + "_processes.html";
}
};
}
const componentsLink = document.getElementById('componentsLink')
if (componentsLink) {
componentsLink.onclick = function() {
window.location.href = determineComponentPath(data);
};
}
// Load cells and layouts the graph
graph.getModel().beginUpdate();
try {
// draw the diagram
draw(graph, parent, layout, data);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
if (mxClient.IS_QUIRKS) {
document.body.style.overflow = 'hidden';
new mxDivResizer(container);
}
}
}