# astah* API 利用ガイド

## 【モデル情報の取得】

1. クラス図のモデル情報の取得
2. アクティビティ図のモデル情報の取得
3. シーケンス図のモデル情報の取得
4. ステートマシン図のモデル情報の取得
5. データフロー図のモデル情報の取得
6. CRUDのモデル情報の取得
7. 図の取得
8. 別名の取得
9. ハイパーリンクの取得
10. フローチャートの基本要素の取得
11. ProjectAccessorから要素を検索

各インターフェース、メソッドの詳細については、astah* APIのJavaDocをご覧ください。

#### 【クラス図のモデル情報の取得】

ここでは、モデル情報の取得方法をクラス図やオブジェクト図、またはサンプルプログラムを併用して一部の例を紹介します。

#### クラスの属性情報の取得

クラス(IClass)のメソッドgetAttributes()を用いることで、属性(IAttribute)の配列を取得できます。クラスが他クラスと 関連している場合、属性情報オブジェクトには関連端の情報も含まれます。
例えば、Class0が属性attribute0とClass1への関連（関連端のロール名class1）を持っている場合は、図の様になります。

#### クラスの操作情報の取得

クラス(IClass)のメソッドgetOperations()を利用することで、操作(IOperation)の配列を取得できます。

#### クラスの依存情報の取得

クラス(IClass)のメソッドgetClientDependencies()を利用することで、そのクラスが依存するクラスに繋がる依存(IDependency)の 配列を取得できます。また、それらに対しメソッドgetSupplier()を用いることで、依存元のクラスを取得できます。
例えば、Class0がClass1に依存している場合の情報は、図の様になります。

#### クラスの実現情報の取得

クラス(IClass)のメソッドgetClientRealizations()を利用することで、そのクラスが実現しているインターフェースクラスに 繋がる実現(IRealization)の配列を取得できます。また、それらに対しメソッドgetSupplier()を用いることで、実現されている インターフェースクラスを取得できます。
例えば、Class1がClass0を実現している場合の情報は、図の様になります。

#### クラスの汎化情報の取得

クラス(IClass)のメソッドgetGeneralizations()を利用することで、そのクラスのスーパークラスに繋がる汎化(IGeneralization)の 配列を取得できます。また、それらの汎化に対しメソッドgetSuperType()を用いることで、スーパークラスを取得できます。
例えば、Class1がClass0を継承している場合の情報は、図の様になります。

#### テンプレートクラスの取得

クラス(IClass)のメソッドgetTemplateBindings()を利用することで、そのクラスのテンプレートクラスに繋がるテンプレートバインディング(ITemplateBinding) の配列を取得できます。テンプレートバインディング(ITemplateBinding)のgetTemplate()を利用することでテンプレートクラスを取得できます。

#### テンプレートクラスのテンプレートパラメータ情報の取得

クラス(IClass)のメソッドgetTemplateParameters()を利用することで、そのクラスのテンプレートパラメータ(IClassifierTemplateParameter)の配列を取得できます。

#### プロジェクトを表す（起点となる）モデルの取得

astah*プロジェクトファイルの全モデル情報は、プロジェクトを表すモデル（以下、プロジェクトモデル）の下にツリー状に存在します。
まずProjectAccessorオブジェクトを取得して、astah*プロジェクトファイルを開きプロジェクトモデル(IModelクラスのオブジェクト)を取得します。
ClassDefinitionBuilder.javaより

            // プロジェクトを開いて、プロジェクトモデルを取得する
            ProjectAccessor prjAccessor = AstahAPI.getAstahAPI().getProjectAccessor();
            prjAccessor.open(inputFile);
            IModel iModel = prjAccessor.getProject();

#### パッケージ配下のパッケージを、再帰的に全て取得

パッケージ(IPackage)を継承するサブシステムやモデルも、パッケージに含めます。
パッケージ(IPackage)の直下にある全モデル要素を、メソッドgetOwnedElements()の利用により 配列として取得し、その中からパッケージのみ抽出します。また、取得したパッケージに対しても 同様の処理を行い、再帰的に全てのパッケージを取得します。
ClassDefinitionBuilder.javaより

        /**
         * 指定パッケージ配下のパッケージを、再帰的に全て取得する。
         *
         * @param iPackage
         *            指定パッケージ
         * @param iPackages
         *            パッケージ一覧を格納するリスト
         * @return パッケージ一覧を格納したリスト
         */
        private List getPackages(IPackage iPackage, List iPackages) {
            INamedElement[] iNamedElements = iPackage.getOwnedElements();
            for (int i = 0; i < iNamedElements.length; i++) {
                INamedElement iNamedElement = iNamedElements[i];
                if (iNamedElement instanceof IPackage) {
                    iPackages.add(iNamedElement);
                    getPackages((IPackage)iNamedElement, iPackages);
                }
            }
            return iPackages;
        }

#### パッケージ配下のクラスの取得

パッケージ(IPackage)直下にある全モデル要素を、メソッドgetOwnedElements()を用いることで配列として取得し、その中からクラスのみを抽出します。
ClassDefinitionBuilder.javaより

        /**
         * 指定パッケージ配下のクラスを取得する。
         *
         * @param iPackage
         *            指定パッケージ
         * @return クラス一覧を格納したリスト
         */
        private List getIClasses(IPackage iPackage) {
            List iClasses = new ArrayList();
            INamedElement[] iNamedElements = iPackage.getOwnedElements();
            for (int i = 0; i < iNamedElements.length; i++) {
                INamedElement iNamedElement = iNamedElements[i];
                if (iNamedElement instanceof IClass) {
                    iClasses.add(iNamedElement);
                }
            }
            return iClasses;
        }

#### クラスのフルパス名の取得

クラス(IClass)を含め、INamedElementのサブクラスの場合、メソッドgetName()を用いることで名前を取得できます。
さらに自分を所有するモデル要素を所得するメソッドgetOwner()を組み合わせることによって、 プロジェクトモデルからのフルパス名を取得できます。
ClassDefinitionBuilder.javaより

        /**
         * クラスの名前をフルパスで取得する
         *
         * @param iClass
         *            クラス
         * @return クラス名（フルパス）
         */
        private String getFullName(IClass iClass) {
            StringBuffer sb = new StringBuffer();
            IElement owner = iClass.getOwner();
            while (owner != null && owner instanceof INamedElement && owner.getOwner() != null) {
                sb.insert(0, ((INamedElement) owner).getName() + "::");
                owner = owner.getOwner();
            }
            sb.append(iClass.getName());
            return sb.toString();
        }

#### 【アクティビティ図のモデル情報の取得】

ここでは、アクティビティ図に関連するモデル情報の取得方法をクラス図とオブジェクト図を併用して、一部の例を紹介します。

#### パーティション情報の取得

アクティビティ(IActivity)のメソッドgetPartitions()を用いることで、パーティション(IPartition)の配列を取得できます。
アクティビティ(IActivity)のメソッドgetSubPartition()とgetSuperParition()を用いることで、パーティション(IPartition)の階層を取得できます。
例えば、Partition0とPartition1の情報は図の様になります。

#### 制御フロー情報の取得

アクティビティ(IActivity)のメソッドgetFlows()を用いることで、制御フロー(IFlow)の配列を取得できます。
アクティビティノード(IActivityNode)のメソッドgetIncomings()とgetOutgoings()を用いることでアクションに関連する制御フローを取得できます。
例えば、二つの制御フローの情報は図の様になります。

#### アクションや開始ノードなどの情報の取得

アクティビティ(IActivity)のメソッドgetActivityNode()を用いることで、アクティビティノード(IActivityNode)の配列を取得できます。
さらにパーティション(IPartition)のメソッドgetActivityNode()を用いることでパーティションに含まれるアクションを取得できます。
例えば、action0と開始ノードの情報は図の様になります。

#### 【シーケンス図のモデル情報の取得】

ここでは、シーケンス図に関連するモデル情報の取得方法をクラス図とオブジェクト図を併用して、一部の例を紹介します。

#### ライフライン情報の取得

インタラクション(IInteraction)のメソッドgetLifelines()を用いることで、ライフライン(ILifeline)の配列を取得できます。
例えば、LifeLine0の情報は図の様になります。

#### 複合フラグメント情報の取得

ライフライン(IInteraction)のメソッドgetFragments()を用いることで、このライフライン(ILifeline)に関連する
複合フラグメント(ICombinedFragment)と<メッセージ(IMessage)の配列を取得できます。
例えば、alt複合フラグメントの情報は、図の様になります。

#### オペランド情報の取得

複合フラグメント(ICombinedFragment)のメソッドgetInteractionOperands()を用いることでオペランド(IInteractionOperand)の配列を取得できます。
例えば、alt複合フラグメントにある二つの複合フラグメントの情報は、図の様になります。

#### メッセージ情報の取得

ライフライン(IInteraction)のメソッドgetFragments()を用いることで、このライフライン(ILifeline)に関連する複合フラグメント(ICombinedFragment)
とメッセージ(IMessage)の配列を取得できます。さらに、ライフライン(IInteraction)のメソッドgetFragments(IInteractionOperand operand)を用いて
特定のオペランドに属するメッセージ(IMessage)の配列を取得できます。
例えば、Message0の情報は図の様になります。

#### 【ステートマシン図のモデル情報の取得】

ここでは、ステートマシン図に関連するモデル情報の取得方法を紹介します。

#### 状態とサブマシン状態情報の取得

ステートマシン図(IStateMachineDiagram)のメソッドgetStateMachine()を用いることで、図のステートマシン(IStateMachine)を取得できます。
図のステートマシン(IStateMachine)のメソッドgetVertexes()を用いて、ステートマシン(IStateMachine)に含まれる状態(IState)の配列を取得できます。
状態(IState)のメソッドisSubmachineState()を用いることでブマシン状態を判定できます。

#### 開始擬似状態と浅い履歴擬似状態、深い履歴擬似状態、フォーク擬似状態などの情報の取得

ステートマシン図(IStateMachineDiagram)のメソッドgetStateMachine()を用いることで、図のステートマシン(IStateMachine)を取得できます。
図のステートマシン(IStateMachine)のメソッドgetVertexes()を用いて、ステートマシン(IStateMachine)に含まれる擬似状態(IPseudoState)の配列を取得できます。
擬似状態(IPseudoState)のisForkPseudostate()などのメソッドを用いることでフォーク擬似状態や開始擬似状態などを判定できます。

#### 【データフロー図のモデル情報の取得】

ここでは、データフロー図に関連するモデル情報の取得方法を紹介します。

#### プロセス情報の取得

データフロー図(IDataFlowDiagram)のメソッドgetDataFlowNodes()を用いることで、プロセス(IProcessBox)の配列を取得できます。
プロセス(IProcessBox)のメソッドgetDataFlowDiagram()を用いて、プロセス(IProcessBox)の詳細を表すデータフロー図(IDataFlowDiagram)を取得できます。

#### データフロー情報の取得

プロセス(IProcessBox)のメソッドgetIncomings()とgetOutgoings()を用いることで、プロセス(IProcessBox)に繋がるデータフローを取得できます。

#### 外部エンティティ情報の取得

データフロー図(IDataFlowDiagram)のメソッドgetDataFlowNodes()を用いることで、外部エンティティ(IExternalEntity)の配列を取得できます。

#### データストア情報の取得

データフロー図(IDataFlowDiagram)のメソッドgetDataFlowNodes()を用いることで、データストア(IDataStore)の配列を取得できます。

#### 【CRUDのモデル情報の取得】

ここでは、CRUDに関連するモデル情報の取得方法を紹介します。

#### ヘッダー情報の取得

CRUD(IMatrixDiagram)のメソッドgetColumnHeaders()とgetRowHeaders()を用いることで、ヘッダーの配列を取得できます。

#### 値情報の取得

CRUD(IMatrixDiagram)のメソッドgetShowValueCell(row, column)を用いることで、特定の行と列の値を取得できます。

### 【図の取得】

名前付き要素(INamedElement)は、図(IDiagram)やパッケージ(IPackage)、パーティション(IPartition)などの親クラスです。
名前付き要素(INamedElement)のメソッドgetDiagrams()を用いることで配下の全図を取得できます。

（例）アクティビティ図の取得

    public List getActivityDiagram(IPackage iPackage) {
        List activityDiagrams = new ArrayList();

        IDiagram[] dgms = iPackage.getDiagrams();
        for (int i = 0; i < dgms.length; i++) {
            IDiagram dgm = dgms[i];
            if (dgm instanceof IActivityDiagram
                    && !((IActivityDiagram )dgm).isFlowChart()) {
                   activityDiagrams.add(dgm);
            }
        }
        return activityDiagrams;
    }

（例）フローチャートの取得

    public List getFlowCharts(IPackage iPackage) {
        List flowCharts = new ArrayList();

        IDiagram[] dgms = iPackage.getDiagrams();
        for (int i = 0; i < dgms.length; i++) {
            IDiagram dgm = dgms[i];
            if (dgm instanceof IActivityDiagram
                    && ((IActivityDiagram )dgm).isFlowChart()) {
                flowCharts.add(dgm);
            }
        }
        return flowCharts ;
    }

### 【別名の取得】

別名の情報は、内部ではタグ付き値として保持しています。タグ付き値にはITaggedValueを通してアクセスできます。
タグ付き値のキーは別名１が"jude.multi_language.alias1"、別名２が"jude.multi_language.alias2"となっておりますので
以下のコードのように取得することが可能です。

（例）別名１の取得

    private static final String KEY_ALIAS1 = "jude.multi_language.alias1";

    private String geAlias1(INamedElement element) {
        ITaggedValue[] tvs = element.getTaggedValues();
        for (int i = 0; i < tvs.length; i++) {
            ITaggedValue tv = tvs[i];
            if (KEY_ALIAS1.equals(tv.getKey())) {
                return tv.getValue();
            }
        }
        return null;
    }

### 【ハイパーリンクの取得】

INamedElementおよびIPresentationはIHyperlinkOwnerを継承しています。
IHyperlinkOwnerのgetHyperlinks()によって保持しているハイパーリンク(IHyperlink)のリストを取得することが可能です。

（例）ハイパーリンクの取得

    private void showHyperlinkStrings(INamedElement element) {

        IHyperlink[] links = element.getHyperlinks();
        for (int i = 0; i < links.length; i++) {
            IHyperlink link = links[i];
            if(link.isFile()) {
                System.out.println(link.getName());
                System.out.println(link.getPath());
                System.out.println(link.getComment());
            } else if(link.isModel()) {
                System.out.println(link.getName());
                System.out.println(link.getPath());
                System.out.println(link.getComment());
            } else if(link.isURL()) {
                System.out.println(link.getName());
                System.out.println(link.getPath());
                System.out.println(link.getComment());
            }
         }
    }

以下の例のように、ハイパーリンクの種類がモデルになる場合、nameがモデルのid、IElementImpのgetId()によって取得することも可能です。

（例）ハイパーリンク文字列

    type=file,name=astah_com.log,path=C:/Documents and Settings,comment= Target is a file
    type=url,name=http://www.change-vision.com,path=http://,comment= Target is a web page
    type=model,name=9a1411-1112fec29a5-0804d01aa6c5fb9fe2aab956b4ca593a,path=,comment= Target is a astah* model

### 【フローチャートの基本要素の取得】

astah*はフローチャートをアクティビティ図の一系統に考えています。アクションにステレオタイプを付加することで、 基本要素オブジェクトを実現しています。

（例）ループ開始要素の取得

    private static final String LOOP_START_ELEMENT = "loop_start";

    public List getLoopStartElements(IActivityDiagram iActivityDiagram) {
       List loopStartElements = new ArrayList();

       IActivity iActivity = iActivityDiagram.getActivity();
       IActivityNode[] activityNodes = iActivity.getActivityNodes();
       for (int i = 0; i < activityNodes.length; i++) {
            IActivityNode node = activityNodes[i];
            String[] stereotypes = node.getStereotypes();
            for (int j = 0; j < stereotypes.length; j++) {
               if (LOOP_START_ELEMENT.equals(stereotypes[j])) {
                   loopStartElements.add(node);
                   break;
               }
            }
        }
        return loopStartElements;
    }

#### 基本要素オブジェクトのステレオタイプ一覧

処理１ <--- 標準アイコンの要素にステレオタイプを付加しません。
処理２(flow_process)
定義済処理 (predefined_process)
手作業 (hand_work)
準備 (preparation)
サーバー(server)
端末(machine)
データ(data)
記憶データ(stored_data)
内部記憶(internal_storage)
順次アクセス(sequential_storage)
ディスク１(disk)
ディスク２(database)
文書(document)
手操作入力(hand_inputting)
表示(display)
判断(judgement)
ループ開始(loop_start)
ループ終了(loop_end)
ページ内結合子(internal_connector)
ページ外結合子(external_connector)

### 【ProjectAccessorから要素を検索】

ProjectAccessorには3つの検索メソッドが用意されています。
public INamedElement[] findElements(Class elementKind, String name) throws ProjectNotFoundException;
要素の種類と名前で要素を検索します。ITopicPresentationなどのプレゼンテーションは検索対象となりません。

（例）findElements(Class elementKind, String name)の使用

    ProjectAccessor prjAccessor = AstahAPI.getAstahAPI().getProjectAccessor();
    prjAccessor.open("C:\\test.asta");
    //classDgm0という名前のクラス図を検索
    INamedElement[] iNamedElements = prjAccessor.findElements(IClassDiagram.class, "classDgm0");
    //Aという名前のクラスを検索
    iNamedElements = prjAccessor.findElements(IClass.class, "A");
    //Bという名前の属性を検索
    iNamedElements = prjAccessor.findElements(IAttribute.class, "B");
    //Cという名前の操作を検索
    iNamedElements = prjAccessor.findElements(IOperation.class, "C");
    //Dという名前の関連を検索

    iNamedElements = prjAccessor.findElements(IAssociation.class, "D");
    //Eという名前のユースケースを検索
    iNamedElements = prjAccessor.findElements(IUseCase.class, "E");
    //Fという名前の包含を検索
    iNamedElements = prjAccessor.findElements(IInclude.class, "F");

    //Gという名前の状態を検索
    iNamedElements = prjAccessor.findElements(IState.class, "G");
    //Hという名前の擬似状態を検索
    iNamedElements = prjAccessor.findElements(IPseudostate.class, "H");
    //Iという名前の遷移を検索
    iNamedElements = prjAccessor.findElements(ITransition.class, "I");

    //Jという名前のパーティションを検索
    iNamedElements = prjAccessor.findElements(IPartition.class, "J");
    //Kという名前のアクションを検索
    iNamedElements = prjAccessor.findElements(IAction.class, "K");
    //Lという名前のオブジェクトノードを検索
    iNamedElements = prjAccessor.findElements(IObjectNode.class, "L");
    //Mという名前のフローを検索
    iNamedElements = prjAccessor.findElements(IFlow.class, "M");

    //Nという名前のライフラインを検索
    iNamedElements = prjAccessor.findElements(ILifeline.class, "N");
    //Oという名前のメッセージを検索
    iNamedElements = prjAccessor.findElements(IMessage.class, "O");

    //Pという名前の外部エンティティを検索
    iNamedElements = prjAccessor.findElements(IExternalEntity.class, "P");
    //Qという名前のデータストアを検索
    iNamedElements = prjAccessor.findElements(IDataStore.class, "Q");

    //Rという名前のERモデルを検索
    iNamedElements = prjAccessor.findElements(IERModel.class, "R");
    //Sという名前のERドメインを検索
    iNamedElements = prjAccessor.findElements(IERDomain.class, "S");
    //USER_DEFINED_DATATYPE1という名前のERデータタイプを検索
    iNamedElements = prjAccessor.findElements(IERDatatype.class, "USER_DEFINED_DATATYPE1");
    //Tという名前のERエンティティを検索
    iNamedElements = prjAccessor.findElements(IEREntity.class, "T");
    //Uという名前のER属性を検索
    iNamedElements = prjAccessor.findElements(IERAttribute.class, "U");
    //Vという名前のERリレーションシップを検索
    iNamedElements = prjAccessor.findElements(IERRelationship.class, "V");
    //Wという名前のERサブタイプリレーションシップを検索
    iNamedElements = prjAccessor.findElements(IERSubtypeRelationship.class, "W");
    //Xという名前のERインデックスを検索
    iNamedElements = prjAccessor.findElements(IERIndex.class, "X");

    prjAccessor.close();

public abstract INamedElement[] findElements(Class elementKind) throws ProjectNotFoundException;
要素の種類で要素を検索します。ITopicPresentationなどのプレゼンテーションは検索対象となりません。

（例）findElements(Class elementKind)の使用 classDgm0という名前のクラス図を検索

    ProjectAccessor prjAccessor = AstahAPI.getAstahAPI().getProjectAccessor();
    prjAccessor.open("C:\\test.asta");
    //クラス図を検索
    INamedElement[] iNamedElements = prjAccessor.findElements(IClassDiagram.class);
    prjAccessor.close();

public INamedElement[] findElements(ModelFinder picker) throws ProjectNotFoundException;
ModelFinderで要素を検索します。

（例）findElements(ModelFinder picker)の使用

        //クラス図を抽出するModelFinderインターフェースを実装したクラス
        class ClassDiagramPicker implements ModelFinder {
            public boolean isTarget(INamedElement namedElement) {
                if (namedElement instanceof IClassDiagram) {
                    return true;
                }
                return false;
            }
        }

    ProjectAccessor prjAccessor = AstahAPI.getAstahAPI().getProjectAccessor();
    prjAccessor.open("C:\\test.asta");
    //classDgm0という名前のクラス図を検索
    INamedElement[] iNamedElements = prjAccessor.findElements(new ClassDiagramPicker());
    prjAccessor.close();

Home