我正在寻找一个生成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个答案... with CodeModel和with Eclipse JDT。
我在我的解决方案中使用了CodeModel: - )
答案 0 :(得分:69)
Sun提供了一个名为CodeModel的API,用于使用API生成Java源文件。获取信息并不是最简单的事情,但它确实存在并且效果非常好。
获取它的最简单方法是作为JAXB 2 RI的一部分 - XJC模式到java生成器使用CodeModel生成其java源,它是XJC jar的一部分。您只能将它用于CodeModel。
抓取答案 1 :(得分:45)
使用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;
}
}
答案 2 :(得分:27)
Eclipse JDT AST的解决方案
谢谢,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();
}
}
答案 3 :(得分: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;
}
}
答案 4 :(得分:9)
另一个替代方案是Eclipse JDT的AST,如果你需要重写任意Java源代码而不仅仅是生成源代码,这是很好的。 (我相信它可以独立于eclipse使用)。
答案 5 :(得分:4)
Eclipse JET项目可用于执行源代码生成。我不认为它的API与你描述的API完全一样,但每次我听说有一个项目在做Java源代码时,他们都使用了JET或自己开发的工具。
答案 6 :(得分:3)
不知道库,但通用模板引擎可能就是您所需要的。有a bunch of them,我个人对FreeMarker
有很好的经验答案 7 :(得分:2)
我构建的东西看起来非常像你的理论DSL,叫做“sourcegen”,但从技术上来说,而不是我写的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回购是here。
答案 8 :(得分:1)
答案 9 :(得分:1)
我自己做了一个模拟生成器工具。即使您需要遵循Sun格式指南,这也是一项非常简单的任务。我打赌你完成的代码会更快,然后你就可以找到符合互联网目标的东西了。
您基本上已经自己概述了API。现在就填写实际代码吧!
答案 10 :(得分:1)
还有StringTemplate。它是由ANTLR的作者而且非常强大。
答案 11 :(得分:1)
有新项目write-it-once。基于模板的代码生成器您使用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;
}
}
答案 12 :(得分:0)
这实际上取决于你想要做什么。代码生成本身就是一个主题。没有特定的用例,我建议查看速度代码生成/模板库。另外,如果您正在离线进行代码生成,我建议使用像ArgoUML这样的东西,从UML图/对象模型到Java代码。
答案 13 :(得分: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//"));
答案 14 :(得分:0)
这是一个看起来很有趣的JSON-to-POJO项目: