Last active
April 28, 2024 08:40
-
-
Save pmduque/68a6fd0f23112fe27392833f4de0b6e5 to your computer and use it in GitHub Desktop.
Export an Archimate view to be imported into draw.io #jarchi #drawio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Author: Pedro Duque | |
* Version: 0.2 | |
* Date: 2022-12-19 | |
* | |
* PURPOSE: | |
* This script exports an Archimate view to imported into draw.io (aka diagrams.net). | |
* | |
* USAGE: | |
* - Select a view in Archi | |
* - Export the view into the selected file | |
* - Open or import the file in Draw.io | |
* - Adjust as necessary | |
* | |
* NOTES: | |
* - Nested shapes will have their relationships represented as transparent lines! | |
* - properties names will be curated: spaces converted to _ | |
* - Doesn't support duplicated properties | |
* | |
* LIMITATIONS: | |
* - Relationships routing in Archi doesn't reflect on draw.io 100% | |
* - No support for specialization | |
* - Some shapes not supported | |
* - No support for labels | |
* | |
* TODO's: | |
* - All alternative shapes support | |
* - Better error/exception handling | |
* - automate the import process | |
* | |
* CREDITS AND INSPIRATION: | |
* smileham / Export View to Markdown (https://gist.github.com/smileham/578bbbb88dc0ed5a1403f3b98711ec25) | |
* christhearchitect / ImportDrawio (https://gist.github.com/christhearchitect/ee35ab560d2d42773a5a982b5e240452) | |
* xmayeur / jArchi library with functions to manage relationship layout in views (https://gist.github.com/xmayeur/bbe80af3d09706b34848b4bbfaa71103) | |
* | |
* CHANGE LOG: | |
* - v0.2: support for utf8, bendpoints, custom shape styles and format. | |
* - v0.1: initial version | |
*/ | |
//***************************************************************************** | |
// CONFIGURATION | |
//***************************************************************************** | |
const useAlternativeShapes=false; //if true the script will be sensible to alternative shapes defined. Otherwise it will use the default shape. | |
const routeConnections=true; //if true, tries to replicate relationship custom routing | |
//***************************************************************************** | |
// | |
// Below there will be dragons! | |
// | |
//***************************************************************************** | |
const strategyColor = "#F5DEAA"; | |
const motivationColor = "#CCCCFF"; | |
const businessColor = "#ffff99"; | |
const applicationColor = "#99ffff"; | |
const technologyColor = "#AFFFAF"; | |
const physicalColor = "#AFFFAF"; | |
const implementationColor = "#FFE0E0"; | |
const implementationColorL = "#E0FFE0"; | |
const groupingColor = ""; | |
const locationColor = "#FFB973"; | |
const junctionAndColor = "#000000"; | |
const junctionOrColor = "#ffffff"; | |
const archiElemMap = new Map([ | |
// Archi type draw.io | |
// --------------------------- ------------------ | |
// STRATEGY | |
["capability", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+strategyColor+";shape=mxgraph.archimate3.application;appType=capability;archiType=rounded;"], | |
["course-of-action", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+strategyColor+";shape=mxgraph.archimate3.application;appType=course;archiType=rounded;"], | |
["resource", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+strategyColor+";shape=mxgraph.archimate3.application;appType=resource;archiType=square;"], | |
//MOTIVATION | |
["stakeholder", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=role;archiType=oct;"], | |
["driver", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=driver;archiType=oct;"], | |
["goal", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=goal;archiType=oct;"], | |
["meaning", "shape=cloud;html=1;whiteSpace=wrap;fillColor="+motivationColor+";"], | |
["outcome", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=outcome;archiType=oct;"], | |
["principle", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=principle;archiType=oct;"], | |
["requirement", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=requirement;archiType=oct;"], | |
["assessment", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=assess;archiType=oct;"], | |
["value", "shape=ellipse;html=1;whiteSpace=wrap;fillColor="+motivationColor+";perimeter=ellipsePerimeter;"], | |
["constraint", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+motivationColor+";shape=mxgraph.archimate3.application;appType=constraint;archiType=oct;"], | |
// ["value-stream", "NOTSUPPORTED", motivationColor], // not supported by draw.io at this time... | |
// BUSINESS | |
["business-actor", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=actor;archiType=square;"], | |
["business-collaboration", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=collab;archiType=square;"], | |
["business-event", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=event;archiType=rounded;"], | |
["business-function", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=func;archiType=rounded;"], | |
["business-interaction", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=interaction;archiType=rounded;"], | |
["business-interface", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=interface;archiType=square;"], | |
["business-object", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.businessObject;overflow=fill;"], | |
["business-process", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=proc;archiType=rounded;"], | |
["business-role", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=role;archiType=square;"], | |
["business-service", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.application;appType=serv;archiType=rounded;"], | |
["product", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.product;"], | |
["contract", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.contract;"], | |
["representation", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+businessColor+";shape=mxgraph.archimate3.representation;"], | |
//APPLICATION | |
["application-collaboration", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=collab;archiType=square"], | |
["application-component", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=comp;archiType=square"], | |
["application-event", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=event;archiType=rounded"], | |
["application-function", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=func;archiType=rounded"], | |
["application-interaction", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=interaction;archiType=rounded"], | |
["application-interface", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=interface;archiType=square"], | |
["application-process", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=proc;archiType=rounded"], | |
["application-service", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.application;appType=serv;archiType=rounded"], | |
["data-object", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+applicationColor+";shape=mxgraph.archimate3.businessObject;overflow=fill"], | |
//TECHNOLOGY | |
["artifact", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=artifact;archiType=square;"], | |
["communication-network", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=netw;archiType=square;"], | |
["device", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.device;"], | |
["system-software", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=sysSw;archiType=square;"], | |
["technology-collaboration", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=collab;archiType=square;"], | |
["technology-event", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=event;archiType=rounded"], | |
["technology-function", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=func;archiType=rounded;"], | |
["technology-interaction", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=interaction;archiType=rounded;"], | |
["technology-interface", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=interface;archiType=square;"], | |
["technology-process", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=proc;archiType=rounded;"], | |
["technology-service", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=serv;archiType=rounded"], | |
["node", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.node;"], | |
["path", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+technologyColor+";shape=mxgraph.archimate3.application;appType=path;archiType=square;"], | |
//PHYSICAL | |
["distribution-network", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+physicalColor+";shape=mxgraph.archimate3.application;appType=distribution;archiType=square;"], | |
["equipment", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+physicalColor+";shape=mxgraph.archimate3.tech;techType=equipment;"], | |
["facility", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+physicalColor+";shape=mxgraph.archimate3.tech;techType=facility;"], | |
["material", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+physicalColor+";shape=mxgraph.archimate3.application;appType=material;archiType=square;"], | |
//IMPLEMENTATION | |
["deliverable", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+implementationColor+";shape=mxgraph.archimate3.deliverable;"], | |
["work-package", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+implementationColor+";shape=mxgraph.archimate3.application;archiType=rounded;"], | |
["gap", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+implementationColorL+";shape=mxgraph.archimate3.gap;"], | |
["plateau", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+implementationColorL+";shape=mxgraph.archimate3.tech;techType=plateau;"], | |
["implementation-event", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+implementationColor+";shape=mxgraph.archimate3.application;appType=event;archiType=rounded;"], | |
//COMPOSITE | |
["location", "html=1;outlineConnect=0;whiteSpace=wrap;fillColor="+locationColor+";shape=mxgraph.archimate3.application;appType=location;archiType=square;"], | |
["grouping", "shape=folder;spacingTop=10;tabWidth=100;tabHeight=25;tabPosition=left;html=1;dashed=1;"], | |
//JUNCTION | |
["junction_and", "ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor="+junctionAndColor+";verticalAlign=top;fillColor=strokeColor"], | |
["junction_or", "ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor="+junctionOrColor+";verticalAlign=top;fillColor="+junctionOrColor] | |
]); | |
// Not (yet) supported: | |
// ["sketch-model-actor", "", ""], | |
// ["sketch-model-sticky", "", ""], | |
// No direct equivalent in draw.io: | |
// ["diagram-model-connection", "", ""], | |
// ["diagram-model-group", "", ""], | |
// ["diagram-model-image", "", ""], | |
// ["diagram-model-note", "", ""], | |
// ["diagram-model-reference", "", ""], | |
// Not (yet) supported: | |
// ["canvas-model-block", "", ""], | |
// ["canvas-model-image", "", ""], | |
// ["canvas-model-sticky" "", ""], | |
const archiRelMap = new Map([ | |
// Archi type draw.io | |
// --------------------------- ------------------ | |
["access-relationship", "html=1;endArrow=none;elbow=vertical;dashed=1;startFill=0;dashPattern=1 4;rounded=0;"], | |
["access-relationship_read", "html=1;startArrow=open;endArrow=none;elbow=vertical;startFill=0;dashed=1;dashPattern=1 4;rounded=0;"], //verificar! | |
["access-relationship_write", "html=1;endArrow=open;elbow=vertical;endFill=0;dashed=1;dashPattern=1 4;rounded=0;"], //verificar! | |
["access-relationship_readwrite", "html=1;endArrow=open;elbow=vertical;endFill=0;dashed=1;startArrow=open;startFill=0;dashPattern=1 4;rounded=0;"], | |
["aggregation-relationship", "html=1;startArrow=diamondThin;startFill=0;elbow=vertical;startSize=10;endArrow=none;rounded=0;"], | |
["assignment-relationship", "endArrow=block;html=1;endFill=1;startArrow=oval;startFill=1;elbow=vertical;rounded=0;"], | |
["association-relationship", "html=1;endArrow=none;elbow=vertical;rounded=0;"], | |
["composition-relationship", "html=1;startArrow=diamondThin;startFill=1;elbow=vertical;startSize=10;endArrow=none;rounded=0;"], | |
["flow-relationship", "html=1;endArrow=block;dashed=1;elbow=vertical;endFill=1;dashPattern=6 4;rounded=0;"], | |
["influence-relationship", ""], | |
["realization-relationship", "html=1;endArrow=block;elbow=vertical;endFill=0;dashed=1;rounded=0;"], | |
["serving-relationship", "html=1;endArrow=open;elbow=vertical;endFill=1;rounded=0;"], | |
["specialization-relationship", "endArrow=block;html=1;endFill=0;elbow=vertical;rounded=0;"], | |
["triggering-relationship", "html=1;endArrow=block;dashed=0;elbow=vertical;endFill=1;rounded=0;"] | |
]); | |
const styleAlign = new Map ([ | |
[1, 'left'], | |
[2, 'center'], | |
[4, 'right'] | |
]); | |
const stylePosition = new Map ([ | |
[0, 'top'], | |
[1, 'middle'], | |
[2, 'bottom'] | |
]); | |
const styleFontStyle = new Map ([ | |
["normal", 0], | |
["bold", 1], | |
["italic", 2], | |
["bolditalic", 3] | |
]); | |
//***************************************************************************** | |
/** | |
* Get all bendpoints of the connection using absolute coordinates | |
* | |
* @param conn - visual conenction | |
* @returns {*[]} - an array of bendpoints | |
* | |
* from: xmayeur / jArchi library with functions to manage relationship layout in views (https://gist.github.com/xmayeur/bbe80af3d09706b34848b4bbfaa71103) | |
*/ | |
//***************************************************************************** | |
function getAbsoluteBendpoints(conn) { | |
let abps = [] | |
conn.getRelativeBendpoints().forEach(bp => { | |
let x = bp.startX + conn.source.bounds.x + conn.source.bounds.width / 2 | |
let y = bp.startY + conn.source.bounds.y + conn.source.bounds.height / 2 | |
// add x/y offset of the embedding objects | |
$(conn.source).parents().forEach(p => { | |
try { | |
x += p.bounds.x | |
y += p.bounds.y | |
} catch (e) { | |
} | |
}) | |
let abp = { | |
x: x, | |
y: y | |
} | |
abps.push(abp) | |
}) | |
return abps | |
} | |
//***************************************************************************** | |
// ensure that the input string can be safely displayed in a XML document | |
// without any special characters being interpreted as tags. | |
//***************************************************************************** | |
function escX(s) { | |
// Decode the string | |
var decodedString = unescape(encodeURIComponent(s));; | |
return decodedString.replace(/&/g, "&") | |
.replace(/</g, "<") | |
.replace(/>/g, ">") | |
.replace(/"/g, """) | |
.replace(/'/g, "'") | |
; | |
} | |
//***************************************************************************** | |
// | |
// generate an XML string representing the properties of the given element | |
// | |
//***************************************************************************** | |
function propertiesTable(element) { | |
var theProperties = element.prop(); | |
var theXML=""; | |
propNames=[]; | |
for (var i=0; i<theProperties.length;i++){ | |
if (propNames.includes(theProperties[i])) { | |
propName=theProperties[i].replace(/ /g, "_").replace(/\n/g,"").replace(/\r/g,""); | |
propValue=escX(element.prop(theProperties[i])) | |
theXML+=` ${propName}="${propValue}"`; | |
propNames.push(theProperties[i]); | |
} | |
} | |
return theXML; | |
} | |
//***************************************************************************** | |
// | |
// deal with composed types | |
// | |
//***************************************************************************** | |
function handleType(e) { | |
var type; | |
switch (e.type) { | |
case "access-relationship": | |
switch (e.concept.accessType) { | |
case "access": | |
type="access-relationship"; | |
break; | |
case "read": | |
type="access-relationship_read"; | |
break; | |
case "write": | |
type="access-relationship_write"; | |
break; | |
case "readwrite": | |
type="access-relationship_readwrite"; | |
break; | |
} | |
break; | |
case "junction": | |
switch (e.concept.junctionType) { | |
case "and": | |
type="junction_and"; | |
break; | |
case "or": | |
type="junction_or"; | |
break; | |
} | |
break; | |
default: | |
type=e.type; | |
break; | |
} | |
return type; | |
} | |
//***************************************************************************** | |
// | |
// modify the style string by replacing or adding a new property and its value | |
// to it. | |
// | |
//***************************************************************************** | |
function handleStyle(style, name, newValue) { | |
if (style.includes(name+"=")) { | |
return style.replace(new RegExp(`;${name}=[^;]*;`),`;${name}=${newValue};`); | |
} else { | |
return style+`${name}=${newValue};`; | |
} | |
} | |
//***************************************************************************** | |
// | |
// If alternative shapes are defined, use them. Otherwise use default shapes. | |
// | |
//***************************************************************************** | |
function handleAlternativeShapes(e,style) { | |
if (e.figureType==1) { | |
switch (e.type) { | |
case "business-actor": | |
style=handleStyle(style,"shape","mxgraph.archimate3.actor"); | |
break; | |
} | |
return style; | |
} | |
} | |
//***************************************************************************** | |
// | |
// Copy the shape custom styles to the style string | |
// | |
//***************************************************************************** | |
function copyStyle(e, style) { | |
if (e.fillColor!==null) { | |
style=handleStyle(style, "fillColor", e.fillColor); | |
} | |
if (e.fontColor !==null) { | |
style=handleStyle(style, "fontColor", e.fontColor); | |
} | |
if (e.fontName !==null) { | |
style=handleStyle(style, "fontFamily", e.fontName); //Probably wrong | |
} | |
if (e.fontSize !==null) { | |
style=handleStyle(style, "fontSize", e.fontSize); | |
} | |
if (e.fontStyle !==null) { | |
style=handleStyle(style, "fontStyle", styleFontStyle.get(e.fontStyle)); | |
} | |
if (e.lineColor !==null) { | |
style=handleStyle(style, "strokeColor", e.lineColor); | |
} | |
if (e.textAlignment !==null) { | |
style=handleStyle(style, "align", styleAlign.get(e.textAlignment)); | |
} | |
if (e.textPosition !==null) { | |
style=handleStyle(style, "verticalAlign", stylePosition.get(e.textPosition)); | |
} | |
if (useAlternativeShapes) { | |
style=handleAlternativeShapes(e,style); | |
} | |
return style; | |
} | |
//***************************************************************************** | |
// | |
// Handle Bendpoint coordinates, Entry and Exit points | |
// | |
//***************************************************************************** | |
function getAbsCoords(e) { | |
let coords={ x:e.bounds.x, y:e.bounds.y, w:e.bounds.width, h:e.bounds.height }; | |
let ancestors=$(e).parents(); | |
ancestors.forEach(p => { | |
//This validation is not correct. It should be an easier way to check if its a shape! | |
if (typeof archiElemMap.get(handleType(p))!=='undefined') { | |
coords.x += p.bounds.x; | |
coords.y += p.bounds.y; | |
} | |
}); | |
return coords; | |
} | |
function handleBendPoints(e) { | |
var xml="" | |
if (e.getRelativeBendpoints() != null) { | |
xml += "<Array as=\"points\">\n"; | |
var bps = getAbsoluteBendpoints(e); | |
for (let p=0; p<bps.length; p++) { | |
xml += "<mxPoint x=\""+bps[p].x+"\" y=\""+bps[p].y+"\" />\n"; | |
} | |
xml += "</Array>\n"; | |
} | |
return xml; | |
} | |
function handleEntryExit(e) { | |
let xml="" | |
if (e.getRelativeBendpoints().length > 0 && typeof e.source.bounds !== 'undefined' && typeof e.target.bounds != 'undefined') { | |
let bps = getAbsoluteBendpoints(e); | |
let s=getAbsCoords(e.source); | |
if (bps[0].x <= s.x) { | |
exitX=0; | |
} else if (s.x+s.w <= bps[0].x ) { | |
exitX=1; | |
} else { | |
exitX = 1.0*(bps[0].x-s.x)/s.w | |
} | |
if (bps[0].y <= s.y) { | |
exitY=0; | |
} else if (s.y+s.h <= bps[0].y ) { | |
exitY=1; | |
} else { | |
exitY = 1.0*(bps[0].y-s.y)/s.h | |
} | |
let t=getAbsCoords(e.target); | |
let n=bps.length-1; | |
if (bps[n].x <= t.x) { | |
entryX=0; | |
} else if (t.x+t.w <= bps[n].x ) { | |
entryX=1; | |
} else { | |
entryX = (bps[n].x-t.x)/t.w | |
} | |
if (bps[n].y <= t.y) { | |
entryY=0; | |
} else if (t.y+t.h <= bps[n].y ) { | |
entryY=1; | |
} else { | |
entryY = (bps[n].y-t.y)/t.h | |
} | |
xml=`exitX=${exitX};exitY=${exitY};entryX=${entryX};entryY=${entryY};`; | |
} | |
return xml; | |
} | |
//***************************************************************************** | |
// | |
// Map all elements into the XML | |
// | |
//***************************************************************************** | |
function mapElements(fw, element, level, parent) { | |
$(element).children().each(function(e) { | |
let newId=e.id; | |
let newName=escX(e.name); | |
let newProps=propertiesTable(e); | |
let style = archiElemMap.get(handleType(e)); | |
//*** Map shapes *** | |
if (typeof style !== 'undefined') { | |
style=copyStyle(e,style); | |
var newElem='<mxCell style="'+ style +'" vertex="1" parent="'+parent+'">\n' | |
+ '<mxGeometry x="'+e.bounds.x+'" y="'+e.bounds.y+'" width="'+e.bounds.width+'" height="'+e.bounds.height+'" as="geometry" />\n' | |
+ '</mxCell>\n' | |
; | |
var newObj = | |
` <object id="${newId}" label="${newName}" ${newProps}> | |
${newElem} | |
</object> | |
`; | |
fw.write(newObj); | |
if ($(e).children().length>0) { | |
mapElements(fw,e,level+1,e.id); | |
} | |
} else { | |
//*** Map relationships *** | |
style = archiRelMap.get(handleType(e)); | |
if (typeof style !== 'undefined') { | |
style=copyStyle(e,style); | |
if (e.source.id==$(e.target).parent().first().id||e.target.id==$(e.source).parents().first().id) { | |
style=handleStyle(style,"strokeColor","none"); | |
} | |
let entryExit=routeConnections?handleEntryExit(e):""; | |
let bendPoints=routeConnections?handleBendPoints(e):""; | |
let newElem='<mxCell style="'+ style + entryExit +'" edge="1" parent="'+parent+'" source="'+e.source.id+'" target="'+e.target.id+'">\n' | |
+ '<mxGeometry width="160" relative="1" as="geometry">\n' | |
+ bendPoints | |
+ '</mxGeometry>\n' | |
+ '</mxCell>\n' | |
; | |
let newObj = | |
` <object id="${newId}" label="${newName}" ${newProps}> | |
${newElem} | |
</object> | |
`; | |
fw.write(newObj); | |
} else { | |
console.log('Not Found: '+e.id+','+e.type+'\n'); | |
} | |
} | |
}); | |
}; | |
// ********************************************************************** | |
// Main flow | |
// ********************************************************************** | |
console.log("Starting to export view to draw.io"); | |
var FileWriter=Java.type("java.io.FileWriter"); | |
var theView = $(selection).filter("archimate-diagram-model").first(); | |
if (theView) { | |
const fileName = window.promptSaveFile({ | |
title: `Draw.io filename for view ${theView.name}`, | |
filterExtensions: ["*.xml"], | |
fileName: `${model.name}_${theView.name}.xml`, | |
}); | |
if(fileName) { | |
const date = new Date(); | |
const timeISOString = date.toISOString(); | |
var fw = new FileWriter(fileName,false); | |
const header = | |
`<?xml version="1.0" encoding="UTF-8"?> | |
<mxfile host="" modified="${timeISOString}" agent="Archi" etag="${model.name}" type="device"> | |
<diagram id="${theView.id}" name="${escX(theView.name)}"> | |
<mxGraphModel dx="2302" dy="697" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | |
<root> | |
<mxCell id="0" /> | |
<mxCell id="1" parent="0" /> | |
`; | |
fw.write(header); | |
// try { | |
mapElements(fw,theView, 0 , "1"); | |
// } catch (err) { | |
// console.log(`An error occurred while exporting the view: ${err}`); | |
// } | |
var footer= | |
` </root> | |
</mxGraphModel> | |
</diagram> | |
</mxfile>\n | |
`; | |
fw.write(footer) | |
fw.close(); | |
console.log("Done exporting view to draw.io"); | |
} | |
} else { | |
console.log("No view selected") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment