Export Astah diagrams to plantUML and mermaid!


There are several ways to generate UML diagrams via texts such as PlantUML and mermaid.

One of Astah users, Evan Chen wrote a script to convert Astah diagrams for PlantUML and mermaid.js. Currently there are scripts for converting Sequence diagrams and Flowcharts.

Script Overview:Astah_Jude_UML_export_to_Markdown-mermaid-Plantuml-
Scripts:

To PlantUML:Sequence Diagrams
To mermaid:Sequence Diagrams / Flowcharts


smarter2 How to use

  1. Create a Sequence Diagram in Astah
    sequence-diagram1.png
  2. Go to [Tool] – [Script Editor] to open the editor. (This menu exists only in version 7.2 or later. If you are using version 7.1 or earlier, install “Script Plug-in” first.)
    script-editor.png
  3. Paste a script to convert Sequence diagram to mermaid.js, then click the arrow icon.
    mermaid1.png
  4. Text gets exported in the window below.
    mermaid2.png
  5. Copy the output and paste in the mermaid.js editor to generate the diagram.
    mermaid2.png
  6. Here’s the sample on PlantUML using the script to convert to PlantUML.
    plantUML.png

Scripts

Convert Sequence diagrams to PlantUML

//  This script convert Astah SequenceDiagram to plantuml fomat text
//  Author:      Chen Zhi
//  E-mail:      cz_666@qq.com
//  License: APACHE V2.0 (see license file)

var ISequenceDiagram = Java.type('com.change_vision.jude.api.inf.model.ISequenceDiagram');
var ILifeline = Java.type('com.change_vision.jude.api.inf.model.ILifeline');
var IMessage = Java.type('com.change_vision.jude.api.inf.model.IMessage');
var HashMap = Java.type('java.util.HashMap');

run();

function run() {

var diagramViewManager = astah.getViewManager().getDiagramViewManager();
var diagram = diagramViewManager.getCurrentDiagram();

if (!(diagram instanceof ISequenceDiagram)) {
print('Open a ISequenceDiagram and run again.');
return;
}

var presentations = diagram.getPresentations();
var lifelinePresentations = getLifelinePresentations(presentations);
var lifelineNames = getLifelineNames(lifelinePresentations);
var messagePresentations = getMassagePresentations(presentations);

print('@startuml');
printLifeline(lifelinePresentations, lifelineNames);
printMessages(messagePresentations, lifelineNames);
print('@enduml');

}

function getLifelinePresentations(presentations) {
var lifelinePresentations = new Array();
for (var i in presentations) {
var presentation = presentations[i];
if (presentation.getModel() instanceof ILifeline) {
lifelinePresentations[i] = presentation;
}
}

lifelinePresentations.sort(orderOfLifelinePosition);
return lifelinePresentations;
}

function orderOfLifelinePosition(a, b) {
return a.getLocation().getX() - b.getLocation().getX();
}

function getLifelineNames(lifelinePresentations) {
var lifelineNames = new HashMap();
for (var i in lifelinePresentations) {
var lifelineP = lifelinePresentations[i];
if (lifelineP == undefined) {
continue;
}
var lifeline = lifelineP.getModel();
if (lifeline.getBase() != null) {
lifelineNames.put(lifeline, lifeline.getName() + "_" + lifeline.getBase().getName());
} else {
lifelineNames.put(lifeline, lifeline.getName());
}
}
return lifelineNames;
}

function printLifeline(lifelinePresentations, lifelineNames) {
for (var i in lifelinePresentations) {
var lifelineP = lifelinePresentations[i];
if (lifelineP == undefined) {
continue;
}
var lifeline = lifelineP.getModel();
print("participant " + lifelineNames.get(lifeline));
}
}

function getMassagePresentations(presentations) {
var messagePresentations = new Array();
for (var i in presentations) {
var presentation = presentations[i];
if (presentation.getModel() instanceof IMessage) {
messagePresentations[i] = presentation;
}
}

messagePresentations.sort(orderOfMessagePosition);
return messagePresentations;
}

function orderOfMessagePosition(a, b) {
return a.getPoints()[0].getY() - b.getPoints()[0].getY();
}

function printMessages(messagePresentations, lifelineNames) {
for (var i in messagePresentations) {
var messageP = messagePresentations[i];
if (messageP == undefined) {
continue;
}

var message = messageP.getModel();
var sourceName = lifelineNames.get(message.getSource());
var targetName = lifelineNames.get(message.getTarget());

print(sourceName + getArrow(message) + targetName + ':' + getText(message));

}
}

function getArrow(message) {
if (message.isReturnMessage()) {
return " -->> ";
}
if (message.isAsynchronous()) {
return " ->> ";
}
return " -> ";
}

function getText(message) {
var index = message.getIndex();
if (message.isReturnMessage()) {
index = "reply";
}
var messageName = message.getName();
if (messageName == null) {
messageName = "";
}
return index + '.' + messageName;
}

Convert Sequence Diagram to mermaid.js

//  This script convert Astah SequenceDiagram to mermaid fomat text
//  Author:      Chen Zhi
//  E-mail:      cz_666@qq.com
//  License: APACHE V2.0 (see license file)

var ISequenceDiagram = Java.type('com.change_vision.jude.api.inf.model.ISequenceDiagram');
var ArrayList = Java.type('java.util.ArrayList');
var Arrays = Java.type('java.util.Arrays');
var Comparator = Java.type('java.util.Comparator');
var Collections = Java.type('java.util.Collections');
var HashMap = Java.type('java.util.HashMap');

var INDENT = '    ';

run();

function run() {

var diagramViewManager = astah.getViewManager().getDiagramViewManager();
var diagram = diagramViewManager.getCurrentDiagram();

if (!(diagram instanceof ISequenceDiagram)) {
print('Open a ISequenceDiagram and run again.');
return;
}

print(diagram + ' Sequence');
print('```mermaid');
print('sequenceDiagram;');

var lifelinePresentations = getLifelinePresentations(diagram);
var lifelineNames = getLifelineNames(lifelinePresentations);
printLifelines(lifelinePresentations, lifelineNames);

var messagePresentations = getMessagePresentations(diagram);
printMessages(messagePresentations, lifelineNames);

print('```');

}

function getLifelinePresentations(diagram) {

var presentations = diagram.getPresentations();

var interaction = diagram.getInteraction();
var lifelines = interaction.getLifelines();

var lifelinePresentations = new ArrayList();
for (var i in presentations) {
var presentation = presentations[i];
if (Arrays.asList(lifelines).contains(presentation.getModel())) {
lifelinePresentations.add(presentation);
}
}

Collections.sort(lifelinePresentations, new Comparator() {
compare: function ( a, b ) {
return a.getLocation().getX() - b.getLocation().getX();
}
});

return lifelinePresentations;

}

function getLifelineNames(lifelinePresentations) {

var lifelineNames = new HashMap();
for (var i in lifelinePresentations) {
var lifeline = lifelinePresentations[i].getModel();
if (lifeline.getBase() != null) {
lifelineNames.put(lifeline, lifeline.getName() + '_' + lifeline.getBase());
} else {
lifelineNames.put(lifeline, lifeline.getName());
}
}

return lifelineNames;

}

function printLifelines(lifelinePresentations, lifelineNames) {

for (var i in lifelinePresentations) {
var lifeline = lifelinePresentations[i].getModel();
print(INDENT + 'participant ' + lifelineNames.get(lifeline) + ';');
}

}

function getMessagePresentations(diagram) {

var interaction = diagram.getInteraction();
var msgs = interaction.getMessages();
var messagePresentations = new ArrayList();
var presentations = diagram.getPresentations();
for (var i in presentations) {
var presentation = presentations[i];
if (Arrays.asList(msgs).contains(presentation.getModel())) {
messagePresentations.add(presentation);
}
}

Collections.sort(messagePresentations, new Comparator() {
compare: function ( a, b ) {
return a.getPoints()[0].getY() - b.getPoints()[0].getY();
}
});

return messagePresentations;

}

function printMessages(messagePresentations, lifelineNames) {

for (var i in messagePresentations) {

var presentation = messagePresentations[i];
var model = presentation.getModel();
var source = model.getSource();
var target = model.getTarget();

print(INDENT + lifelineNames.get(source) + getArrowString(model)
+ lifelineNames.get(target) + ':' + getIndexString(model) + '.' + model.getName());

}

}

function getIndexString(model) {

if (model.isReturnMessage()) {
return 'reply';
}

return model.getIndex();

}

function getArrowString(model) {

if (model.isReturnMessage()) {
return '-->>';
}

if (model.isAsynchronous()) {
return '-x';
}

return '->>';

}

Convert Flowcharts to mermaid.js

//  This script convert Astah flowchart to mermaid fomat text
//  Author:      Chen Zhi
//  E-mail:      cz_666@qq.com
//  License: APACHE V2.0 (see license file)

var IActivityDiagram = Java.type('com.change_vision.jude.api.inf.model.IActivityDiagram');
var IControlNode = Java.type('com.change_vision.jude.api.inf.model.IControlNode');
var HashMap = Java.type('java.util.HashMap');

var ID_PREFIX = 'A';
var REPLACEMENT_CHAR = '?';
var INDENT = '    ';

run();

function run() {

var diagramViewManager = astah.getViewManager().getDiagramViewManager();
var diagram = diagramViewManager.getCurrentDiagram();
if (!(diagram instanceof IActivityDiagram)) {
print('Open a flowchart and run again.');
return;
}

if (!(diagram.isFlowChart())) {
print('Open a flowchart and run again.');
return;
}

var activity = diagram.getActivity();
var activityNodes = activity.getActivityNodes();
var activityNodeIds = getActivityNodeIds(activityNodes);
var flows = activity.getFlows();

print(diagram + ' Flowchart');
print('```mermaid');
print('graph TB');
printObjectDefine(activityNodes, activityNodeIds);
printFlowchartLogic(flows, activityNodeIds);
print('```');

}

function getActivityNodeIds(activityNodes) {
var activityNodeIds = new HashMap();
for (var i in activityNodes) {
var nodeId = ID_PREFIX + i;
var node = activityNodes[i];
activityNodeIds.put(node, nodeId);
}
return activityNodeIds;
}

function printObjectDefine(activityNodes, activityNodeIds) {
for (var i in activityNodes) {
var node = activityNodes[i];
var nodeId = activityNodeIds.get(node);
if (isRhombus(node)) {
print(INDENT + nodeId + '{' + replaceUnavailableCharacters(node.getName()) + '}');
continue;
}
if (isRectangle(node)) {
print(INDENT + nodeId + '[' + replaceUnavailableCharacters(node.getName()) + ']');
continue;
}
print(INDENT + nodeId + '(' + replaceUnavailableCharacters(node.getName()) + ')');
}
}

function replaceUnavailableCharacters(string) {

var newString = string.replace(/\n/g, ' ');

newString = newString.replace(/\(/g, REPLACEMENT_CHAR);
newString = newString.replace(/\)/g, REPLACEMENT_CHAR);
newString = newString.replace(/\[/g, REPLACEMENT_CHAR);
newString = newString.replace(/\]/g, REPLACEMENT_CHAR);
newString = newString.replace(/\{/g, REPLACEMENT_CHAR);
newString = newString.replace(/\}/g, REPLACEMENT_CHAR);
newString = newString.replace(/\;/g, REPLACEMENT_CHAR);
newString = newString.replace(/\|/g, REPLACEMENT_CHAR);
newString = newString.replace(/E/g, REPLACEMENT_CHAR);

return newString;
}

function printFlowchartLogic(flows, activityNodeIds) {

for (var i in flows) {
var flow = flows[i];
var sourceId = activityNodeIds.get(flow.getSource());
if (sourceId == null) {
continue;
}
var targetId = activityNodeIds.get(flow.getTarget());
if (targetId == null) {
continue;
}
if (flow.getGuard() != "") {
print(INDENT + sourceId + "-->|" + replaceUnavailableCharacters(flow.getGuard()) + "| " + targetId);
continue;
}
print(INDENT + sourceId + "-->" + targetId);
}
}

function isRhombus(node) {
if (node instanceof IControlNode && node.isDecisionMergeNode()) {
return true;
}
var stereotypes = node.getStereotypes();
return stereotypes.length > 0 && 'judgement'.equals(stereotypes[0]);
}

function isRectangle(node) {
var stereotypes = node.getStereotypes();
return stereotypes.length > 0 && 'flow_process'.equals(stereotypes[0]);
}

Leave a comment