Javaソースファイルを生成するJava API [終了]


127

Javaソースファイルを生成するフレームワークを探しています。

次のAPIのようなもの:

X clazz = Something.createClass("package name", "class name");
clazz.addSuperInterface("interface name");
clazz.addMethod("method name", returnType, argumentTypes, ...);

File targetDir = ...;
clazz.generate(targetDir);

次に、Javaソースファイルがターゲットディレクトリのサブディレクトリにあります。

誰かがそのようなフレームワークを知っていますか?


編集

  1. ソースファイルが本当に必要です。
  2. メソッドのコードも記入したいと思います。
  3. 直接のバイトコード操作/生成ではなく、高レベルの抽象化を探しています。
  4. オブジェクトのツリーに「クラスの構造」も必要です。
  5. 問題ドメインは一般的です。「共通の構造」なしで、非常に異なるクラスを大量に生成することです。

SOLUTIONS
私は...あなたの答えに基づいて、2件の回答を掲載しているCodeModelとし、EclipseのJDTと

私は私のソリューションでCodeModelを使用しました:-)


あなたの質問は非常に一般的です、あなたの問題領域は本当にこの一般的ですか?問題のドメインについて具体的に説明できますか?たとえば、重複する例外クラスコードの排除や列挙型の重複の排除など、特定の問題のコードを生成するコード生成ツールを作成しました。
グレッグマット

@Vlookward:以下の2つの別々の回答として、質問に入力した回答を移動できます。次に、質問からそれぞれへのリンクを追加します。
アンデターナー

@Banengusk:お問い合わせいただきありがとうございます。インターネットの最も暗い部分を検索する時間を節約できました。@skaffman:素晴らしい発見-あなたは彼の次のタスクで別の開発者をより安心させました:)
Ran Biron

このSOの回答は、JavaではなくC ++の質問に対応していますが、回答はJavaにも有効です。 stackoverflow.com/a/28103779/120163
Ira Baxter

回答:


70

Sunは、APIを使用してJavaソースファイルを生成するためのCodeModelと呼ばれるAPIを提供しています。情報を取得するのは最も簡単なことではありませんが、そこにあり、非常にうまく機能します。

それを手に入れる最も簡単な方法は、JAXB 2 RIの一部としてです。XJCスキーマからJavaへのジェネレーターは、CodeModelを使用してJavaソースを生成し、XJC jarの一部です。CodeModelにのみ使用できます。

http://codemodel.java.net/から取得します


2
それは私が必要とするものです!シンプルで完全に機能します。ありがとう、スカフマン!
Daniel Fanjul 2008


@ykaganovichグッドコール。[ repo.maven.apache.org/maven2/com/sun/codemodel/…CDDLおよびGPLでライセンスされています)。以前のコメントを削除しました。
Brad Cupit 14

46

CodeModel
ありがとう、skaffmanで解決策が見つかりました

たとえば、次のコードでは:

JCodeModel cm = new JCodeModel();
JDefinedClass dc = cm._class("foo.Bar");
JMethod m = dc.method(0, int.class, "foo");
m.body()._return(JExpr.lit(5));

File file = new File("./target/classes");
file.mkdirs();
cm.build(file);

私はこの出力を得ることができます:

package foo;
public class Bar {
    int foo() {
        return  5;
    }
}

これは素晴らしいですね。CodeModelでも生成されている別の型を返すメソッドをどのように生成しますか?
アンドラーシュハマー


@AndrásHummerはから返されたインスタンスcm._class(...)をの戻り型引数として使用しますdc.method(...)
HugoBaés、2015年

28

Eclipse JDTのAST
Thanks、Gilesで見つかったソリューション

たとえば、次のコードでは:

AST ast = AST.newAST(AST.JLS3);
CompilationUnit cu = ast.newCompilationUnit();

PackageDeclaration p1 = ast.newPackageDeclaration();
p1.setName(ast.newSimpleName("foo"));
cu.setPackage(p1);

ImportDeclaration id = ast.newImportDeclaration();
id.setName(ast.newName(new String[] { "java", "util", "Set" }));
cu.imports().add(id);

TypeDeclaration td = ast.newTypeDeclaration();
td.setName(ast.newSimpleName("Foo"));
TypeParameter tp = ast.newTypeParameter();
tp.setName(ast.newSimpleName("X"));
td.typeParameters().add(tp);
cu.types().add(td);

MethodDeclaration md = ast.newMethodDeclaration();
td.bodyDeclarations().add(md);

Block block = ast.newBlock();
md.setBody(block);

MethodInvocation mi = ast.newMethodInvocation();
mi.setName(ast.newSimpleName("x"));

ExpressionStatement e = ast.newExpressionStatement(mi);
block.statements().add(e);

System.out.println(cu);

私はこの出力を得ることができます:

package foo;
import java.util.Set;
class Foo<X> {
  void MISSING(){
    x();
  }
}

質問してもいいですか。JavaEclipseプラグインの一部としてこれを実行しましたか、それともスタンドアロンコードとして使用できましたか?これは何年も前のものだと思います。
mtrc 2013年

@mtrc私がよく覚えている場合、それはEclipseのスタンドアロンで通常のJavaプロジェクトであり、適切なjarをクラスパスに追加しましたが、ファイル名は覚えていません。
Daniel Fanjul 2013年

17

Roaster(https://github.com/forge/roaster)を使用してコードを生成できます。

次に例を示します。

JavaClassSource source = Roaster.create(JavaClassSource.class);
source.setName("MyClass").setPublic();
source.addMethod().setName("testMethod").setPrivate().setBody("return null;")
           .setReturnType(String.class).addAnnotation(MyAnnotation.class);
System.out.println(source);

次の出力が表示されます。

public class MyClass {
   private String testMethod() {
       return null;
   }
}

9

もう1つの代替手段はEclipse JDTのASTです。これは、ソースコードを生成するだけでなく、任意のJavaソースコードを書き換える必要がある場合に適しています。(そしてそれは日食とは独立して使用できると私は信じています)。


1
すごい!!抽象構文ツリーが私が探しているものです...今、私はAPIについての詳細情報を検索します...ありがとう!、:-)
Daniel Fanjul

予想通り、APIは複雑です。しかし、それは私が必要とするすべての機能を備えています。ありがとう、ジャイルズ。
Daniel Fanjul 2008

1
@gastaldiが述べたように、(JBoss Forgeの)roasterはEclipse JDTの優れたラッパーです。JDTの複雑さを隠し、Javaコードを解析、変更、または作成するための優れたAPIを提供します。github.com/forge/roaster
Jmini、

4

EclipseのJETのプロジェクトは、ソース生成を行うために使用することができます。APIはあなたが説明したものとまったく同じではないと思いますが、Javaソース生成を行うプロジェクトについて耳にするたびに、彼らはJETまたは自社開発ツールを使用しました。



2

私は「sourcegen」と呼ばれる、理論上のDSLに非常によく似たものを作成しましたが、技術的には、私が書いたORMのutilプロジェクトの代わりに作成しました。DSLは次のようになります。

@Test
public void testTwoMethods() {
    GClass gc = new GClass("foo.bar.Foo");

    GMethod hello = gc.getMethod("hello");
    hello.arguments("String foo");
    hello.setBody("return 'Hi' + foo;");

    GMethod goodbye = gc.getMethod("goodbye");
    goodbye.arguments("String foo");
    goodbye.setBody("return 'Bye' + foo;");

    Assert.assertEquals(
    Join.lines(new Object[] {
        "package foo.bar;",
        "",
        "public class Foo {",
        "",
        "    public void hello(String foo) {",
        "        return \"Hi\" + foo;",
        "    }",
        "",
        "    public void goodbye(String foo) {",
        "        return \"Bye\" + foo;",
        "    }",
        "",
        "}",
        "" }),
    gc.toCode());
}

https://github.com/stephenh/joist/blob/master/util/src/test/java/joist/sourcegen/GClassTest.java

また、パラメーター/戻り値型のFQCNの「インポートの自動編成」、このcodegenの実行で変更されなかった古いファイルの自動プルーニング、内部クラスのインデントなどのきちんとした処理も行います。

生成されたコードは、コードの他の部分と同じように、警告なし(使用されていないインポートなど)ではなく、見栄えがよいはずです。非常に多くの生成されたコードを読むのは醜いです...それは恐ろしいことです。

とにかく、ドキュメントはあまりありませんが、APIはかなりシンプルで直感的だと思います。Mavenリポジトリは、興味があればここにあります


1

ソースが本当に必要な場合、ソースを生成するものは何も知りません。ただし、ASMまたはCGLIBを使用して、.classファイルを直接作成できます。

これらからソースを生成できるかもしれませんが、私はそれらをバイトコードの生成にのみ使用しました。


1

私はモックジェネレータツールのために自分でやっていました。Sunのフォーマットガイドラインに従う必要がある場合でも、これは非常に単純なタスクです。あなたはインターネットであなたの目標に合うものを見つけたよりも速くそれを行うコードを完成させるでしょう。

基本的に、自分でAPIの概要を説明しました。今すぐ実際のコードを入力してください!


Hehehe ...フレームワークが見つからない場合は、私が作成します。たくさんの機能が欲しいので、朝にそれを取得しません...
ダニエルFanjul


1

新しいプロジェクトのライト・イット・ワンスがあります。テンプレートベースのコードジェネレータ。Groovyを使用してカスタムテンプレートを記述し、Javaリフレクションに応じてファイルを生成します。これは、ファイルを生成する最も簡単な方法です。AspectJファイル、JPAアノテーションに基づくSQL、列挙型に基づく挿入/更新などを生成することにより、getters / settest / toStringを作成できます。

テンプレートの例:

package ${cls.package.name};

public class ${cls.shortName}Builder {

    public static ${cls.name}Builder builder() {
        return new ${cls.name}Builder();
    }
<% for(field in cls.fields) {%>
    private ${field.type.name} ${field.name};
<% } %>
<% for(field in cls.fields) {%>
    public ${cls.name}Builder ${field.name}(${field.type.name} ${field.name}) {
        this.${field.name} = ${field.name};
        return this;
    }
<% } %>
    public ${cls.name} build() {
        final ${cls.name} data = new ${cls.name}();
<% for(field in cls.fields) {%>
        data.${field.setter.name}(this.${field.name});
<% } %>
        return data;
    }
}

0

それは本当にあなたが何をしようとしているのかに依存します。コード生成はそれ自体のトピックです。特定のユースケースがなければ、速度コード生成/テンプレートライブラリを検討することをお勧めします。また、コード生成をオフラインで行う場合は、ArgoUMLなどを使用してUMLダイアグラム/オブジェクトモデルからJavaコードに移行することをお勧めします。


0

例:1 /

private JFieldVar generatedField;

2 /

String className = "class name";
        /* package name */
        JPackage jp = jCodeModel._package("package name ");
         /*  class name  */
        JDefinedClass jclass = jp._class(className);
        /* add comment */
        JDocComment jDocComment = jclass.javadoc();
        jDocComment.add("By AUTOMAT D.I.T tools : " + new Date() +" => " + className);
        // génération des getter & setter & attribues

            // create attribue 
             this.generatedField = jclass.field(JMod.PRIVATE, Integer.class) 
                     , "attribue name ");
             // getter
             JMethod getter = jclass.method(JMod.PUBLIC, Integer.class) 
                     , "attribue name ");
             getter.body()._return(this.generatedField);
             // setter
             JMethod setter = jclass.method(JMod.PUBLIC, Integer.class) 
                     ,"attribue name ");
             // create setter paramétre 
             JVar setParam = setter.param(getTypeDetailsForCodeModel(Integer.class,"param name");
             // affectation  ( this.param = setParam ) 
             setter.body().assign(JExpr._this().ref(this.generatedField), setParam);

        jCodeModel.build(new File("path c://javaSrc//"));

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.