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.  

  4. ウィンドウ上部に、mermaid.js用テキスト変換スクリプトを貼り付けます。三角のボタンを押します。
  5. ウィンドウ下部にテキストが出力されました。script-editor3.png
  6.  

  7. これをコピーして、mermaid.js側のエディタに貼り付けると、mermaid.js側で図が表示されます。
    mermaid2.png
  8.  
    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]);
}
Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s