124 votes

Une API Java pour générer des fichiers sources Java

Je suis à la recherche d'un cadre pour générer des fichiers sources 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 doit être trouvé dans un sous-répertoire du répertoire cible.

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


EDIT :

  1. J'ai vraiment besoin des fichiers sources.
  2. Je voudrais également remplir le code des méthodes.
  3. Je cherche une abstraction de haut niveau, pas une manipulation/génération directe de bytecode.
  4. J'ai également besoin de la "structure de la classe" dans un arbre d'objets.
  5. Le domaine du problème est général : générer une grande quantité de classes très différentes, sans "structure commune".

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

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

69voto

skaffman Points 197885

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

Le moyen le plus simple de s'en procurer est de l'intégrer à JAXB 2 RI - le générateur de schéma XJC vers Java utilise CodeModel pour générer sa source Java, et il fait partie des jars XJC. Vous pouvez l'utiliser uniquement pour le CodeModel.

Prenez-le sur http://codemodel.java.net/

45voto

Daniel Fanjul Points 2375

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 cette sortie :

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

27voto

Daniel Fanjul Points 2375

Solution trouvée avec l'AST d'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 cette sortie :

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

17voto

gastaldi Points 91

Vous pouvez utiliser la torréfaction ( https://github.com/forge/roaster ) pour faire la génération de 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;
   }
}

9voto

Squirrel Points 555

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X