クラスの総数を表示する

次は、実践的なプラグインを作成してみましょう。設計されたモデルの品質を評価する際、指標としてクラスの総数を利用することがあります。Hello Worldの代わりに、astah*モデル内のクラスの総数を表示するプラグインを作成してみましょう。

課題
次のastah*モデルでは、クラスの総数は3つです。

プラグインによって追加したメニューを押した時に

「There are 3 classes」

と表示されるようにしてみましょう。


モデル情報を取得する

astah*のモデル情報を取得するために、astah* APIを活用してみましょう。astah* APIとは、astah*のモデルデータを活用するアプリケーションを開発するためのJavaインタフェース群です。
参考:
astah* professional, UML APIガイド
astah* SysML APIガイド
astah* System Safety APIガイド

これから書くコードでは、ProjectAccessorから現在開いているastah*モデルのルートモデルを取得し、再帰的にすべてのクラスを取得します。それではクラスの総数をメッセージダイアログに表示するようにHello Worldプラグインを修正してみましょう。
まず、CountClassActionクラスを作成しましょう。

/*
 * パッケージ名は、生成したプラグインのパッケージ名よりも
 * 下に移してください。
 * プラグインのパッケージ名=> com.example
 *   com.change_vision.astah.extension.plugin => X
 *   com.example                                     => O
 *   com.example.internal                          => O
 *   learning                                          => X
 */
package com.example.actions;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import com.change_vision.jude.api.inf.AstahAPI;
import com.change_vision.jude.api.inf.exception.ProjectNotFoundException;
import com.change_vision.jude.api.inf.model.IClass;
import com.change_vision.jude.api.inf.model.IModel;
import com.change_vision.jude.api.inf.model.INamedElement;
import com.change_vision.jude.api.inf.model.IPackage;
import com.change_vision.jude.api.inf.project.ProjectAccessor;
import com.change_vision.jude.api.inf.ui.IPluginActionDelegate;
import com.change_vision.jude.api.inf.ui.IWindow;

public class CountClassAction implements IPluginActionDelegate {
  public Object run(IWindow window) throws UnExpectedException {
    try {
      AstahAPI api = AstahAPI.getAstahAPI();
      ProjectAccessor projectAccessor = api.getProjectAccessor();
      IModel iCurrentProject = projectAccessor.getProject();
      List<IClass> classeList = new ArrayList<IClass>();
      getAllClasses(iCurrentProject, classeList);
      JOptionPane.showMessageDialog(window.getParent(),
          "There are " + classeList.size() + " classes.");
    } catch (ProjectNotFoundException e) {
      String message = "Please open a project";
      JOptionPane.showMessageDialog(window.getParent(), message,
          "Warning", JOptionPane.WARNING_MESSAGE);
      throw new CalculateUnExpectedException();
    } catch (Exception e) {
      JOptionPane.showMessageDialog(window.getParent(),
          "Exception occured", "Alert", JOptionPane.ERROR_MESSAGE);
      throw new UnExpectedException();
    }
    return null;
  }

  public class CalculateUnExpectedException
	extends UnExpectedException {
  }

  private void getAllClasses(INamedElement element, List<IClass> classList)
      throws ClassNotFoundException, ProjectNotFoundException {
    if (element instanceof IPackage) {
      for(INamedElement ownedNamedElement :
			((IPackage)element).getOwnedElements()) {
        getAllClasses(ownedNamedElement, classList);
      }
    } else if (element instanceof IClass) {
      classList.add((IClass)element);
      for(IClass nestedClasses : ((IClass)element).getNestedClasses()) {
        getAllClasses(nestedClasses, classList);
      }
    }
  }
}

次に、plugin.xmlファイルにCountClassActionクラスを使ったメニューを追加しましょう。

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <extension point="com.change_vision.astah.ui.actionSets">
    <actionSet
	      label="%action_set_label "
	      visible="true"
	      id="com.example.actions.actionSet1">
      <menu
	        label="%sample_menu"
	        id="sampleMenu"
	        path="tool/sampleMenu">
      </menu>
      <action
	        label="%count_classes"
	        icon="icons/sample.gif"
	        class="com.example.actions.CountClassAction"
	        tooltip="Count classes"
	        menubarPath="tool/sampleMenu/"
	        id="com.example.actions.CountClassdAction">
      </action>
    </actionSet>
  </extension>
</plugin>

最後に、plugin.propertiesに追加したメニューのラベルを追加します。

count_classes=Count classes(C)

これで、クラスの数をカウントした結果を表示できます。



デバッグしてみましょう

ネストクラスのClassCとパッケージ以下のClassAを、再帰的に取得できるかデバッグしながら、確認してみましょう。デバッグをするには次のコマンドを実行します。

> astah-debug

すると、44000ポートがリモートデバッグ用のポートとして開かれた状態で起動します。IDEなどからこのポートに接続し、リモートデバッグします。


例・Eclipseを使ったリモートデバッグ

Eclipseでは下図のように設定します。


設定後、Debugボタンを押すとリモートデバッグが始まります。適当な場所にブレークポイントを設定して実行すると、デバッグが行われます。
なお、リモートデバッグの詳細については、本書で扱う範囲外のため割愛します。