astah*で描いた図をPlantUMLやmermaid用に変換


テキストベースで手軽にUML図を描画できるPlantUMLmermaid
astah*ユーザーEvan Chenさんが、astah*で描いた図をPlantUMLやmermaid.js用にテキスト変換するスクリプトを書いてくださいました。astah*で描いた図の共有オプション等として、どうぞご活用ください。
現在変換に対応している図種は、シーケンス図とフローチャートです。

スクリプト概要:Astah_Jude_UML_export_to_Markdown-mermaid-Plantuml-

スクリプト:

To PlantUML:シーケンス図
To mermaid:シーケンス図 / フローチャート


smarter2 使い方 (例:シーケンス図)

  1. astah*でシーケンス図を描きます
    sequence-diagram1.png
  2. [ツール] – [スクリプトエディタ]を選択して[スクリプトエディタ]ウィンドウを開きます。
    (astah* 7.2をご利用の場合は、[スクリプトエディタ]が同梱されているため、当メニューがあります。
    7.1以前をご利用の方は、[スクリプトエディタ]プラグインをインストールしてください)
    script-editor.png
  3. ウィンドウ上部に、mermaid.js用テキスト変換スクリプトを貼り付けます。三角のボタンを押します。
  4. ウィンドウ下部にテキストが出力されました。script-editor3.png
  5. これをコピーして、mermaid.js側のエディタに貼り付けると、mermaid.js側で図が表示されます。
    mermaid2.png
  6. PlantUMLに貼り付けた場合は、こうなります。
    plantUML.png


スクリプト

シーケンス図を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;
}

 

シーケンス図をmermaid用に変換

//  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 '->>';

}

 

フローチャートをmermaid用に変換

//  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]);
}

One thought on “astah*で描いた図をPlantUMLやmermaid用に変換

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s