2008-09-23 4 views
121

Я ищу фреймворк для генерации исходных файлов Java.Java API для генерации исходных файлов 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 должен находиться в подкаталоге целевого каталога.

Кто-нибудь знает такие рамки?


EDIT:

  1. Мне очень нужны исходные файлы.
  2. Я также хотел бы заполнить код методов.
  3. Я ищу высокоуровневую абстракцию, а не прямое манипулирование/генерацию байт-кода.
  4. Мне также нужна «структура класса» в дереве объектов.
  5. Проблемный домен является общим: для генерации большого количества очень разных классов без «общей структуры».

РЕШЕНИЯ
Я отправил 2 ответы, основанные на ваши ответы ... with CodeModel и with Eclipse JDT.

Я использовал CodeModel в моем решении, :-)

+0

Ваш вопрос очень общий, ваш проблемный домен действительно этот общий? Можете ли вы более подробно рассказать о своей проблемной области? Например, я написал инструменты генерации кода для генерации кода для конкретных проблем, таких как устранение дублирующего кода класса исключений или устранение дублирования в перечислениях. – 2008-09-23 14:59:35

+0

@Vlookward: Вы можете перенести ответы, которые вы разместили в Вопросе, как 2 отдельных ответа ниже. Затем добавьте ссылку на каждый из Вопроса. – 2008-09-25 17:34:54

+0

О, да. Хорошая идея. – 2008-09-25 20:52:48

ответ

68

Sun предоставляет API под названием CodeModel для генерации исходных файлов Java с использованием API.Это не самая легкая вещь, чтобы получить информацию, но она там, и она работает очень хорошо.

Самый простой способ получить это как часть JAXB 2 RI - генератор схемы XJC-to-java использует CodeModel для генерации своего источника java и является частью баннеров XJC. Вы можете использовать его только для CodeModel.

захватить его из http://codemodel.java.net/

1

Если вам действительно нужен источник, я не знаю ничего, что генерирует источник. Однако вы можете использовать ASM или CGLIB, чтобы напрямую создавать файлы .class.

Возможно, у вас есть возможность генерировать исходный код, но я использовал их только для генерации байт-кода.

+0

Мне действительно нужны исходные файлы. Благодаря! – 2008-09-23 15:06:20

4

Проект Eclipse JET может использоваться для создания источника. Я не думаю, что это API так же, как и тот, который вы описали, но каждый раз, когда я слышал о проекте, использующем создание источника Java, они использовали JET или домашний инструмент.

1

Я делал это сам для макета генератора. Это очень простая задача, даже если вам нужно следовать инструкциям по форматированию Sun. Бьюсь об заклад, вы закончите код, который сделает это быстрее, чем вы нашли что-то, что соответствует вашей цели в Интернете.

Вы в основном описали API самостоятельно. Просто заполните его фактическим кодом сейчас!

+0

Hehehe ... Если рамки не найдено, я собираюсь написать ее. Я бы хотел много функциональности, поэтому я не получу его утром ... – 2008-09-23 15:20:09

9

Другая альтернатива АСТ Eclipse JDT, которая хороша, если вам нужно переписать произвольный исходный код Java, а не просто генерировать исходный код. (и я считаю, что он может использоваться независимо от затмения).

+1

Отлично! Абстрактное дерево синтаксиса - это то, что я ищу ... Теперь я буду искать дополнительную информацию об API ... Спасибо !, :-) – 2008-09-23 15:31:45

+0

API сложный, как я и ожидал. Но у него есть все необходимые функции. Спасибо, Джайлс. – 2008-09-23 16:00:07

3

Не знаю об библиотеке, но вам может понадобиться общий механизм шаблонов. Есть a bunch of them, у меня лично был хороший опыт работы с FreeMarker

44

Решение найдено с 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; 
    } 
} 
27

решение найдено с AST Eclipse JDT в
Спасибо, 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(); 
    } 
} 
0

Это действительно зависит от того, что вы пытаетесь сделать. Генерация кода - это тема внутри себя. Без конкретного варианта использования я предлагаю просмотреть библиотеку генерации скоростей/шаблонов. Кроме того, если вы создаете генерацию кода в автономном режиме, я бы предложил использовать что-то вроде ArgoUML для перехода от UML-диаграммы/модели объекта к Java-коду.

2

Я построил что-то похожее на ваш теоретический 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

Она также делает некоторые аккуратные вещи, как «Авто-организовать импорт» любых FQCNs в параметрах/возвращающих типы, автоматическое отсечение все старые файлы, которые не были затронуты в этом codegen run, правильно отступы внутренних классов и т. д.

Идея состоит в том, что сгенерированный код должен быть красивым, чтобы смотреть на него без предупреждений (неиспользуемых импортов и т. д.), так же как и остальная часть вашего кода. Так много сгенерированного кода уродливо читать ... это ужасно.

Во всяком случае, документов не так много, но я считаю, что API довольно прост/интуитивно понятен. Maven repo - here, если кому-то интересно.

0

Exemple: 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//")); 
1

Существует новый проект write-it-once. Генератор кода на основе шаблонов.Вы пишете собственный шаблон с помощью Groovy и сгенерируете файл в зависимости от java-отражений. Это самый простой способ создания любого файла. Вы можете создать getters/settest/toString, создав файлы AspectJ, SQL на основе аннотаций JPA, вставки/обновления на основе перечислений и т. Д.

Пример шаблона:

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; 
    } 
} 
16

Вы можете использовать жаровня (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; 
    } 
} 
Смежные вопросы