【Eclipse】ExecutionEventオブジェクトからICompilationUnitオブジェクトを生成する方法

`ICompilationUnit`オブジェクトはJavaソースファイル一つを表すオブジェクトであり、ASTを構築するときに必要となる。ASTを構築すれば、Javaソース内の情報の取得・操作が直感的に行えるため便利である。
イベントハンドラで受け取る`ExecutionEvent`オブジェクトから、イベント発生時の編集対象であるJavaソースファイルの`ICompilationUnit`オブジェクトを生成する方法について書き残す。現時点で3通りの方法を見つけている。

## 最も直感的な方法

1. アクティブなエディタの編集対象を取得
2. 編集対象のファイルを取得
3. ファイルからJavaソースのオブジェクトを生成

```java
// インポート宣言
import java.util.Optional;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.handlers.HandlerUtil;

// メソッド定義
public Object execute(ExecutionEvent e) throws ExecutionException {
    ICompilationUnit source = Optional.of(e)
        .map(HandlerUtil::getActiveEditorInput)
        .map(input -> (IFileEditorInput)input)
        .map(input -> input.getFile())
        .map(JavaCore::createCompilationUnitFrom)
        .orElse(null);

    return null;
}
```

* エディタの編集対象がファイル以外の場合、`HandlerUtil.getActiveEditorInput`メソッドの戻り値は`IFileEditorInput`オブジェクトではないので、ダウンキャスト時に例外が発生する。
* エディタの編集対象がJavaソースファイル以外のテキストファイルである場合、`JavaCore.createCompilationUnitFrom`メソッドで例外が発生する。
* `IFileEditorInput`インターフェースの依存プラグインは、org.eclipse.uiではなくorg.eclipse.ui.ideなので注意。

## アダプタを利用した方法その1

1. アクティブなエディタの編集対象を取得
2. 編集対象のオブジェクトに、ファイルオブジェクトを下さいと頼む
3. 受け取ったファイルオブジェクトから、Javaソースのオブジェクトを生成

```java
// インポート宣言
import java.util.Optional;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.ui.handlers.HandlerUtil;

// メソッド定義
public Object execute(ExecutionEvent e) throws ExecutionException {
    ICompilationUnit source = Optional.of(e)
        .map(HandlerUtil::getActiveEditorInput)
        .map(input -> input.getAdapter(IFile.class))
        .map(JavaCore::createCompilationUnitFrom)
        .orElse(null);

    return null;
}
```

* エディタの編集対象がファイル以外の場合でも、`input.getAdapter(IFile.class)`の戻り値が`null`となるだけで、特に例外は発生せず処理が終了する（`source`変数に`null`が入る）。
* エディタの編集対象がJavaソースファイル以外のテキストファイルである場合、Javaソースのオブジェクト生成時に例外が発生する。

## アダプタを利用した方法その2

1. アクティブなエディタの編集対象を取得
2. 編集対象のオブジェクトに、Java要素を下さいと頼む
3. 受け取ったJava要素はJavaソースのオブジェクトなのでダウンキャスト

```java
// インポート宣言
import java.util.Optional;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.ui.handlers.HandlerUtil;

// メソッド定義
public Object execute(ExecutionEvent e) throws ExecutionException {
    ICompilationUnit source = Optional.of(e)
        .map(HandlerUtil::getActiveEditorInput)
        .map(input -> (ICompilationUnit)input.getAdapter(IJavaElement.class))
        .orElse(null);
    
    return null;
}
```

* エディタの編集対象がファイル以外であっても、Javaソースファイル以外のテキストファイルであっても、`input.getAdapter(IJavaElement.class)`の戻り値が`null`となるだけで、特に例外は発生せず処理が終了する（`source`変数に`null`が入る）。
* `input.getAdapter(IJavaElement.class)`の戻り値が`ICompilationUnit`オブジェクト以外の場合は例外が発生するが、戻り値が`ICompilationUnit`オブジェクト以外ということは多分ない…と思う。