Я ищу фреймворк для создания исходных файлов 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 ответа на основе ваших ответов ... с CodeModel и с Eclipse JDT.
Я использовал в своем решении CodeModel :-)
@Vlookward: вы можете переместить ответы, которые вы разместили в вопросе, как два отдельных ответа ниже. Затем добавьте ссылку на каждый из Вопросов.
@Banengusk: Спасибо, что спросили, сэкономили мне часы на поиск в самых темных уголках Интернета. @skaffman: Отличная находка - вы помогли другому разработчику легче справиться с его предстоящей задачей :)
Этот SO-ответ касается вопроса для C++, а не для Java, но ответ работает и для Java. stackoverflow.com/a/28103779/120163




Проект Eclipse JET может использоваться для генерации исходного кода. Я не думаю, что этот API в точности похож на тот, который вы описали, но каждый раз, когда я слышал о проекте, выполняющем генерацию исходного кода Java, они использовали JET или самодельный инструмент.
Я сам делал это для инструмента генератора макетов. Это очень простая задача, даже если вам нужно следовать рекомендациям Sun по форматированию. Бьюсь об заклад, вы закончите код, который делает это быстрее, чем вы найдете что-то, что соответствует вашей цели в Интернете.
Вы в основном сами обрисовали API. Просто заполните его настоящим кодом прямо сейчас!
Хе-хе-хе ... Если фреймворк не найдется, я его напишу. Хотелось бы много функционала, чтобы утром не получу ...
Другой альтернативой является AST Eclipse JDT, который хорош, если вам нужно переписать произвольный исходный код Java, а не просто генерировать исходный код. (и я считаю, что его можно использовать независимо от затмения).
Большой!! Я ищу абстрактное синтаксическое дерево ... Теперь я буду искать дополнительную информацию об API ... Спасибо !, :-)
Как я и ожидал, API сложен. Но в нем есть вся необходимая мне функциональность. Спасибо, Джайлз.
Как упоминал @gastaldi, roaster (из JBoss Forge) - хорошая оболочка для Eclipse JDT. Он скрывает сложность JDT и предоставляет удобный API для синтаксического анализа, изменения или написания кода Java. github.com/forge/roaster
Не знаю библиотеки, но общий шаблонизатор может быть всем, что вам нужно. Есть куча из них, лично у меня был хороший опыт с FreeMarker
Sun предоставляет API под названием CodeModel для создания исходных файлов Java с помощью API. Это не самый простой способ получить информацию, но он есть и работает очень хорошо.
Самый простой способ получить его - это часть JAXB 2 RI - генератор схемы XJC в java использует CodeModel для генерации своего исходного кода java, и он является частью jar-файлов XJC. Вы можете использовать его только для CodeModel.
Скачайте его из http://codemodel.java.net/
Это как раз то, что мне нужно! Просто и полностью функционально. Спасибо, скаффман!
@BradCupit Согласно pom-файлу repo.maven.apache.org/maven2/com/sun/codemodel/codemodel/2.6 /…, это CDDL + GPL glassfish.java.net/public/CDDL+GPL_1_1.html
@ykaganovich Хороший звонок. Это [repo.maven.apache.org/maven2/com/sun/codemodel/… под лицензией CDDL и GPL). Я удалил свой предыдущий комментарий.
Решение найдено с помощью 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;
}
}
Это выглядит потрясающе. Как создать метод, который возвращает другой тип, который также создается с помощью CodeModel?
@DrH, простой поиск в Google: codemodel.java.net/nonav/apidocs/com/sun/codemodel/…
@ AndrásHummer использует экземпляр, возвращаемый cm._class(...), в качестве аргумента возвращаемого типа для dc.method(...).
Решение найдено с помощью Eclipse JDT's 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();
}
}
Могу я спросить - вы сделали это как часть подключаемого модуля Java Eclipse или вам удалось использовать это как отдельный код? Я понимаю, что это уже много лет.
@mtrc Если я хорошо помню, это был автономный и нормальный java-проект в eclipse, добавляющий надлежащую банку в путь к классам, но я не помню имя файла.
Также есть StringTemplate. Он разработан автором ANTLR и довольно мощный.
Это действительно зависит от того, что вы пытаетесь сделать. Генерация кода - это отдельная тема. Без конкретного варианта использования я предлагаю взглянуть на библиотеку генерации кода скорости / шаблонов. Кроме того, если вы выполняете генерацию кода в автономном режиме, я бы предложил использовать что-то вроде ArgoUML для перехода от диаграммы / объектной модели UML к Java-коду.
Я построил что-то очень похожее на ваш теоретический 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 в параметрах / возвращаемых типах, автоматическая обрезка любых старых файлов, которые не были затронуты при этом прогоне кодогенератора, правильное создание отступов для внутренних классов и т. д.
Идея состоит в том, что сгенерированный код должен быть красивым, без предупреждений (неиспользованный импорт и т. д.), Как и остальная часть вашего кода. Так много сгенерированного кода некрасиво читать ... это ужасно.
В любом случае, документов не так много, но я думаю, что API довольно прост / интуитивно понятен. Репозиторий Maven - здесь, если кому-то интересно.
Пример: 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//"));
Появился новый проект напиши один раз. Генератор кода на основе шаблонов. Вы пишете собственный шаблон, используя Groovy, и генерируете файл в зависимости от отражений Java. Это самый простой способ создать любой файл. Вы можете создавать геттеры / 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;
}
}
Вы можете использовать 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;
}
}
Вот интересный проект JSON-to-POJO:
Ваш вопрос очень общий, действительно ли ваша проблемная область такая общая? Не могли бы вы подробнее рассказать о своей проблемной области? Например, я написал инструменты генерации кода для генерации кода для конкретных задач, таких как устранение повторяющегося кода класса исключения или устранение дублирования в перечислениях.