Java ソース ファイルを生成する Java API [終了]
-
02-07-2019 - |
質問
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 ソース ファイルがターゲット ディレクトリのサブディレクトリに見つかるはずです。
誰かそのようなフレームワークを知っていますか?
編集:
- 本当にソースファイルが必要なのです。
- メソッドのコードも記入したいと思います。
- 直接のバイトコード操作/生成ではなく、高レベルの抽象化を探しています。
- オブジェクトのツリー内の「クラスの構造」も必要です。
- 問題のドメインは一般的です。「共通の構造」を持たずに、まったく異なるクラスを大量に生成すること。
ソリューション
あなたの回答に基づいて2つの回答を投稿しました... コードモデルあり そして Eclipse JDTを使用.
利用した コードモデル 私の解決策では、:-)
解決
Sun は、API を使用して Java ソース ファイルを生成するための CodeModel と呼ばれる API を提供しています。情報を入手するのはそれほど簡単なことではありませんが、情報は存在し、非常にうまく機能します。
これを入手する最も簡単な方法は、JAXB 2 RI の一部として使用することです。XJC schema-to-java ジェネレーターは CodeModel を使用して Java ソースを生成し、これは XJC jar の一部です。CodeModel のみに使用できます。
から掴んでください http://codemodel.java.net/
他のヒント
CodeModel で見つかった解決策
ありがとう、 スカフマン.
たとえば、次のコードの場合:
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;
}
}
Eclipse JDTのASTで見つかった解決策
ありがとう、 ジャイルズ.
たとえば、次のコードの場合:
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();
}
}
ロースター(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;
}
}
もう 1 つの代替手段は、Eclipse JDT の AST です。これは、ソース コードを生成するだけでなく、任意の Java ソース コードを書き直す必要がある場合に適しています。(Eclipse から独立して使用できると思います)。
の エクリプスジェット プロジェクトを使用してソース生成を行うことができます。そのAPIがあなたが説明したものとまったく同じであるとは思いませんが、Javaソース生成を行うプロジェクトについて聞くたびに、彼らはJETまたは自家製ツールを使用していました。
私は理論上の DSL によく似た「sourcegen」と呼ばれるものを構築しましたが、技術的には ORM のユーティリティ プロジェクトではなく、私が作成したものです。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 リポジトリは ここ 興味のある人がいたら。
モックジェネレーターツールを自分で作成していました。Sun のフォーマット ガイドラインに従う必要がある場合でも、これは非常に簡単な作業です。インターネットで目的に合ったものを見つけるよりも、そのコードを速く完成させることができると思います。
基本的に API の概要を自分で説明しました。今すぐ実際のコードを入力してください。
もあります 文字列テンプレート. 。ANTLR の作者によるもので、非常に強力です。
新しいプロジェクトがあります 一度だけ書き込む. 。テンプレートベースのコードジェネレーター。次を使用してカスタム テンプレートを作成します グルーヴィー, 、Javaリフレクションに応じてファイルを生成します。これはファイルを生成する最も簡単な方法です。AspectJファイルの生成、JPAアノテーションに基づくSQL、enumに基づく挿入/更新などにより、getter/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;
}
}
それは本当にあなたが何をしようとしているかによって異なります。コード生成自体がトピックです。特定の使用例がない場合は、速度コード生成/テンプレート ライブラリを検討することをお勧めします。また、オフラインでコード生成を行っている場合は、ArgoUML などを使用して UML 図/オブジェクト モデルから Java コードに移行することをお勧めします。
例: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//"));
以下は興味深い JSON-to-POJO プロジェクトです。