Top / Eclipse / プラグイン開発のTIPS集 / Javaプロジェクトを操作する

Eclipse/プラグイン開発のTIPS集/ソースコードを解析するパーサASTParserEclipse/プラグイン開発のTIPS集/org.eclipse.jdt.core.ICompilationUnitでもちょっとやりましたが、パッケージ・エクスプローラからSelection経由でICompilationUnit?*1を取得することができました。その Javaソースは、何とかっていう名前のJavaプロジェクトに属しているわけですが、Javaプロジェクト自体を操作するインタフェースもEclipseに用意されています。Javaプロジェクトを作成したり、削除したり、ソースを生成したりすることができるわけですね。以下にJavaプロジェクトを操作する方法をまとめておきます。

パッケージ・エクスプローラを見てもわかるとおり、Javaプロジェクトはツリー構造になってるわけで、よくあるコンポジットパタンになってます。コンポジットな要素たち全部が拡張しているルートのインタフェースがorg.eclipse.jdt.core.IJavaElementです。

org.eclipse.jdt.core.IJavaElement?

全ての要素が拡張しているインタフェースですね。定数を見るとわかるのですが、要素は

int JAVA_MODEL = 1;
int JAVA_PROJECT = 2;
int PACKAGE_FRAGMENT_ROOT = 3;
int PACKAGE_FRAGMENT = 4;
int COMPILATION_UNIT = 5;
int CLASS_FILE = 6;
int TYPE = 7;
int FIELD = 8;
int METHOD = 9;
int INITIALIZER = 10;
int PACKAGE_DECLARATION = 11;
int IMPORT_CONTAINER = 12;
int IMPORT_DECLARATION = 13;
int LOCAL_VARIABLE = 14;
int TYPE_PARAMETER = 15;

くらい種類があるようです。

org.eclipse.jdt.core.IJavaModel

ワークスペース内のJavaモデル(?)のルートです。IJavaElement?#getJavaModel?()で取得することができます。んがいまいちパッケージ・エクスプローラ上の概念でどこを指してるのかわからないですね。ただ

IJavaProject[] getJavaProjects();
IJavaProject getJavaProject(String name);
IWorkspace getWorkspace();

などのメソッドを持っているようです。

org.eclipse.jdt.core.IJavaProject

Javaプロジェクトです。 IJavaElement?#getJavaProject?() で取得することができます。よってコンポジットのどの要素からもJavaプロジェクトへの参照が得られるわけです。

org.eclipse.jdt.core.IPackageFragmentRoot

Javaプロジェクト内のパッケージ階層のトップ要素です。ソースディレクトリやjarファイルなどに対応します。

たとえば

IPackageFragmentRoot root = null;
try {
  IJavaProject javaProject = element.getJavaProject();
  IPackageFragmentRoot[] roots = javaProject
      .getPackageFragmentRoots();
  for (IPackageFragmentRoot rootTmp : roots) {
    if (rootTmp.getKind() == IPackageFragmentRoot.K_SOURCE) {
      root = rootTmp;          ↑ソースディレクトリだったら
    }
  }
} catch (JavaModelException e) {
  e.printStackTrace();
}

などとしてソースディレクトリを取得することができます。

他にもいろいろ確認してみた

他にも以下のやり方でソースディレクトリが取得できそうです。他にもいろいろメソッドを実行して試してみました。

ICompilationUnit.png

上のようなディレクトリ構成で、いろいろなメソッドを実行しました。

System.out.println("Path: " + element.getPath());
System.out.println("Parent: " + element.getParent().getPath());
System.out.println("PrimaryElement: "
        + element.getPrimaryElement().getPath());
System.out.println("Primary: " + element.getPrimary().getPath());
IPackageFragmentRoot root = (IPackageFragmentRoot) element
        .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
System.out.println("Ancestor: " + root.getPath());

elementはキャプチャ内のBL.javaを指しているICompilationUnit?のインスタンスです。

実行結果は以下の通り:

Path: /HogeProject/src/nu/mine/kino/BL.java
Parent: /HogeProject/src/nu/mine/kino
PrimaryElement: /HogeProject/src/nu/mine/kino/BL.java
Primary: /HogeProject/src/nu/mine/kino/BL.java
Ancestor: /HogeProject/src

IJavaElement?#getAncestor(int ancestorType) メソッドで、要素の型(JAVA_PROJECTとかPACKAGE_FRAGMENT_ROOTとか)を指定して上位ディレクトリのIJavaElement?を取得することができます。上の例では

IPackageFragmentRoot root = (IPackageFragmentRoot) element
       .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);

として、BL.javaが入っているディレクトリのトップ階層つまりsrcディレクトリへの参照を取得しています。*2

他のメソッドについてですが IJavaElement?#getParent() については真上のディレクトリですね。他のヤツは、、んー全部BL.javaなんですよね。一応、JavaDocへのリンクを載せておきます。。

パッケージを作る

上の方法でソースディレクトリのIPackageFragmentRoot?を取得し、IPackageFragmentRoot?のメソッド

IPackageFragment createPackageFragment(
   String name,
   boolean force,
   IProgressMonitor monitor)

を呼び出すことで、パッケージを作成することができます。たとえばさっきのelementのディレクトリ nu.mine.kino の下にsampleというパッケージを作成するには

String elementName = element.getParent().getElementName();
String sample = "sample";
String newPackage = "".equals(elementName) ? sample
                    : elementName + "." + sample;
IPackageFragment packageDir = root.createPackageFragment(
                                newPackage, true,new NullProgressMonitor());

とします。単純に文字列連結だと、elementがデフォルトパッケージの時の条件分岐が必要になっちゃいますが、まあよしとしましょう*3

org.eclipse.jdt.core.IPackageFragment

上の例の

IPackageFragment createPackageFragment(
   String name,
   boolean force,
   IProgressMonitor monitor)

で返ってくるオブジェクトが IPackageFragment? です。つまりパッケージを表すインタフェースですね。このインタフェースにはJavaソースコードを生成する

ICompilationUnit createCompilationUnit(
      String name, String contents,
      boolean force, IProgressMonitor monitor)

というメソッドがあります。

ICompilationUnit hoge = packageDir.createCompilationUnit(
        "Hoge.java", "public class Hoge{}", true,
        new NullProgressMonitor());
IPackageDeclaration declaration = hoge.createPackageDeclaration(
        newPackage, new NullProgressMonitor());

こんな感じでソースコードを生成することができるんですね。

org.eclipse.jdt.core.ICompilationUnit?

Javaのソースコードですね。ソースコードを解析するパーサASTParser にも書きましたが以下のようにソースコードの情報を取得できます。elementがICompilationUnit?のインスタンスです。

logger.debug("ファイル名: " + element.getElementName());// ファイル名
String sourceName = element.getElementName().substring(0,
element.getElementName().lastIndexOf("."));
logger.debug("クラス名: " + sourceName);
logger.debug("クラスの完全修飾クラス名: "
  + element.getType(sourceName).getFullyQualifiedName());
logger.debug("パッケージ名: " + element.getParent().getElementName());
String source = cu.getPath().toPortableString();
logger.debug("ソースへのパス: " + source);

実行結果は以下の通り。

ファイル名: BL.java
クラス名: BL
クラスの完全修飾クラス名: nu.mine.kino.BL
パッケージ名: nu.mine.kino
ソースへのパス: /Samples/source/nu/mine/kino/BL.java

ただ 完全修飾クラス名 を取得するメソッドは、そのファイルのクラス名を取得しているのではなく*4、elementのパッケージ名に引数のクラス名を連結してるだけ、、みたいです。

ソースコードのIResourceインスタンスを取得する。

JDT周りをやってるとIResouce系を忘れてしまいそうですが、ありました。

// ソースコードに対応するファイルのIResource
IResource resource = cu.getCorrespondingResource();

これでOKですね。

関連リンク


この記事は

選択肢 投票
おもしろかった 10  
そうでもない 3  

Top / Eclipse / プラグイン開発のTIPS集 / Javaプロジェクトを操作する

現在のアクセス:20801


*1 Javaのソースとかですね
*2 test/hogehogeをソースディレクトリとしてたら、testでなくてtest/hogehogeのへの参照が得られました
*3 デフォルトパッケージの時はelement.getParent().getElementName?()は""(空文字)なんですね
*4 引数にクラス名渡してるくらいだから

添付ファイル: fileICompilationUnit.png 683件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-03-03 (火) 16:25:28 (1385d)