Question

Je recherche un cadre permettant de générer des fichiers source Java.

Quelque chose comme l’API suivante:

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

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

Ensuite, un fichier source Java devrait être trouvé dans un sous-répertoire du répertoire cible.

Quelqu'un connaît-il un tel cadre?

MODIFIER :

  1. J'ai vraiment besoin des fichiers source.
  2. Je voudrais aussi compléter le code des méthodes.
  3. Je recherche une abstraction de haut niveau, et non une manipulation / génération de code secondaire directe.
  4. J'ai également besoin de la " structure de la classe " dans un arbre d'objets.
  5. Le problème est général: générer un grand nombre de classes très différentes, sans "structure commune".

SOLUTIONS
J'ai posté 2 réponses basées sur vos réponses ... avec CodeModel et ??avec Eclipse JDT .

J'ai utilisé CodeModel dans ma solution: -)

Était-ce utile?

La solution

Sun fournit une API appelée CodeModel pour générer des fichiers source Java à l'aide d'une API. Ce n’est pas la chose la plus facile à obtenir, mais c’est là et cela fonctionne extrêmement bien.

Le moyen le plus simple de l'obtenir consiste à utiliser l'interface JAXB 2 - le générateur de schéma XJC vers java utilise CodeModel pour générer son code source Java, qui fait également partie des fichiers jar XJC. Vous pouvez l'utiliser uniquement pour le CodeModel.

Récupérez-le à partir de http://codemodel.java.net/

Autres conseils

Solution trouvée avec CodeModel
Merci, skaffman .

Par exemple, avec ce code:

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);

Je peux obtenir ce résultat:

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

Solution trouvée avec l'AST de Eclipse JDT
Merci, Giles .

Par exemple, avec ce code:

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);

Je peux obtenir ce résultat:

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

Vous pouvez utiliser Roaster ( https://github.com/forge/roaster ) pour générer du code.

Voici un exemple:

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);

affichera la sortie suivante:

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

Une autre alternative est l'AST de Eclipse JDT, qui est utile si vous devez réécrire du code source Java arbitraire plutôt que de simplement générer du code source. (et je pense qu’il peut être utilisé indépendamment d’eclipse).

Le projet Eclipse JET peut être utilisé pour générer des sources. Je ne pense pas que son API ressemble exactement à celle que vous avez décrite, mais chaque fois que j'ai entendu parler d’un projet générant des sources en Java, ils utilisaient JET ou un outil développé localement.

Vous ne connaissez pas de bibliothèque, mais un moteur de modèle générique pourrait suffire. Il y a plusieurs d'entre eux , j'ai personnellement eu une bonne expérience avec FreeMarker

J'ai construit quelque chose qui ressemble beaucoup à votre DSL théorique, appelé "sourcegen", mais techniquement au lieu d'un projet util pour un ORM que j'ai écrit. Le DSL ressemble à:

@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

Il propose également des fonctionnalités intéressantes, telles que "Organiser automatiquement les importations". tous les FQCNs dans les types paramètres / retour, élagage automatique de tout ancien fichier qui n’a pas été touché lors de l’exécution de ce codegen, indentation correcte des classes internes, etc.

L'idée est que le code généré doit être joli à regarder, sans avertissements (importations inutilisées, etc.), tout comme le reste de votre code. Tellement de code généré est moche à lire ... c'est horrible.

Quoi qu’il en soit, il n’ya pas beaucoup de documentation, mais je pense que l’API est assez simple / intuitive. Le référentiel Maven est ici si quelqu'un est intéressé.

Si vous avez VRAIMENT besoin de la source, je ne sais rien qui puisse en générer. Vous pouvez toutefois utiliser ASM ou CGLIB pour créer directement les fichiers .class.

Vous pourrez peut-être générer des sources à partir de celles-ci, mais je ne les ai utilisées que pour générer du bytecode.

Je le faisais moi-même pour un outil générateur de maquette. C'est une tâche très simple, même si vous devez suivre les instructions de mise en forme de Sun. Je parie que vous finiriez le code qui le fait plus rapidement que vous avez trouvé quelque chose qui correspond à votre objectif sur Internet.

Vous avez essentiellement décrit l’API vous-même. Remplissez-le simplement avec le code actuel maintenant!

Il existe également un StringTemplate . Il est par l'auteur de ANTLR et est assez puissant.

Il existe un nouveau projet write-it-once . Générateur de code basé sur un modèle. Vous écrivez un modèle personnalisé à l'aide de Groovy et générez un fichier en fonction des réflexions Java. C'est le moyen le plus simple de générer un fichier. Vous pouvez créer des getters / settest / toString en générant des fichiers AspectJ, SQL basé sur des annotations JPA, des insertions / mises à jour basées sur des énumérations, etc.

.

Exemple de modèle:

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

Cela dépend vraiment de ce que vous essayez de faire. La génération de code est un sujet en soi. Sans cas d'utilisation spécifique, je suggère de regarder la bibliothèque de génération / code de vélocité. De plus, si vous effectuez la génération de code hors ligne, je suggérerais d'utiliser quelque chose comme ArgoUML pour passer du modèle diagramme / objet UML au code Java.

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

Voici un projet JSON-to-POJO qui semble intéressant:

http://www.jsonschema2pojo.org/

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top