Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I'm looking for a framework to generate Java source files.
Something like the following API:
X clazz = Something.createClass("package name", "class name");
clazz.addSuperInterface("interface name");
clazz.addMethod("method name", returnType, argumentTypes, ...);
File targetDir = ...;
clazz.generate(targetDir);
Then, a java source file should be found in a sub-directory of the target directory.
Does anyone know such a framework?
EDIT:
I really need the source files.
I also would like to fill out the code of the methods.
I'm looking for a high-level abstraction, not direct bytecode manipulation/generation.
I also need the "structure of the class" in a tree of objects.
The problem domain is general: to generate a large amount of very different classes, without a "common structure".
SOLUTIONS
I have posted 2 answers based in your answers... with CodeModel and with Eclipse JDT.
I have used CodeModel in my solution, :-)
Sun provides an API called CodeModel for generating Java source files using an API. It's not the easiest thing to get information on, but it's there and it works extremely well.
The easiest way to get hold of it is as part of the JAXB 2 RI - the XJC schema-to-java generator uses CodeModel to generate its java source, and it's part of the XJC jars. You can use it just for the CodeModel.
Grab it from http://codemodel.java.net/
Solution found with CodeModel
Thanks, skaffman.
For example, with this 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);
I can get this output:
package foo;
public class Bar {
int foo() {
return 5;
}
}
Solution found with Eclipse JDT's AST
Thanks, Giles.
For example, with this 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);
I can get this output:
package foo;
import java.util.Set;
class Foo<X> {
void MISSING(){
x();
}
}
You can use Roaster (https://github.com/forge/roaster) to do code generation.
Here is an example:
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);
will display the following output:
public class MyClass {
private String testMethod() {
return null;
}
}
Another alternative is Eclipse JDT's AST which is good if you need to rewrite arbitrary Java source code rather than just generate source code.
(and I believe it can be used independently from eclipse).
The Eclipse JET project can be used to do source generation. I don't think it's API is exactly like the one you described, but every time I've heard of a project doing Java source generation they've used JET or a homegrown tool.
Don't know of a library, but a generic template engine might be all you need. There are a bunch of them, I personally have had good experience with FreeMarker
I built something that looks very much like your theoretical DSL, called "sourcegen", but technically instead of a util project for an ORM I wrote. The DSL looks like:
#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
It also does some neat things like "Auto-organize imports" any FQCNs in parameters/return types, auto-pruning any old files that were not touched in this codegen run, correctly indenting inner classes, etc.
The idea is that generated code should be pretty to look at it, with no warnings (unused imports, etc.), just like the rest of your code. So much generated code is ugly to read...it's horrible.
Anyway, there is not a lot of docs, but I think the API is pretty simple/intuitive. The Maven repo is here if anyone is interested.
If you REALLY need the source, I don't know of anything that generates source. You can however use ASM or CGLIB to directly create the .class files.
You might be able to generate source from these, but I've only used them to generate bytecode.
I was doing it myself for a mock generator tool. It's a very simple task, even if you need to follow Sun formatting guidelines. I bet you'd finish the code that does it faster then you found something that fits your goal on the Internet.
You've basically outlined the API yourself. Just fill it with the actual code now!
There is also StringTemplate. It is by the author of ANTLR and is quite powerful.
There is new project write-it-once. Template based code generator. You write custom template using Groovy, and generate file depending on java reflections. It's the simplest way to generate any file. You can make getters/settest/toString by generating AspectJ files, SQL based on JPA annotations, inserts / updates based on enums and so on.
Template example:
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;
}
}
It really depends on what you are trying to do. Code generation is a topic within itself. Without a specific use-case, I suggest looking at velocity code generation/template library. Also, if you are doing the code generation offline, I would suggest using something like ArgoUML to go from UML diagram/Object model to Java code.
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//"));
Here is a JSON-to-POJO project that looks interesting:
http://www.jsonschema2pojo.org/
Related
What I mean by comment:
/**
*My Comment from database
*/
My Problem:
I got a bunch of DTO's which are not commented at all. However, there are comments in the SQL-Database. I can get these comments by sending a query and then retrieving the ResultSet.
My task is to create a javadoc-API (as HTML and inside the javacode) with the comments from the SQL-Database in order to make the codebase better understandable.
I have written a small java program that retrieves the comments from the sql-database.
I write the found comment into the file with the desired javadoc comment format shown above.
No text in the comment column means null for the comment (which is ok!)
For clarification here are pictures before and after. (dont worry about the text being german)
This is what it looks like right now
This is how it should look like after
As mentioned at the start.. Can I generate Javadoc comments (like this) with the help of a custom doclet? I got told that my solution with a simple java programm was good, but it would be better to make a doclet for this task.
What have I tried:
I read up on a couple of Doclet Overviews, Javadoc FAQ's and Tutorials regarding the topic. I have found out that you can extend the Doclet class from com.sun.javadoc.*; to override the start(RootDoc root) method.
With this I could print fields, tags and methods of classes in a desired package with the help of this custom doclet.
Other than this usecase, I have found no further details on how to actually write your own Doclets.
Is it even possible to write a doclet which generates javadoc comments in your code? Or would it just be better to use my existing solution for the problem?
This is my custom doclet right now:
package myPackage;
import com.sun.javadoc.*;
public class ListClass extends Doclet{
public static void main(String[] args) {
String[] blarg = new String[] {
"-private", //shows private fields and methods
"-doclet",
"myPackage.ListClass", //Doclet to use
"-sourcepath",
"C:/DEV/workspace_jss/MyTestProject/src", //path to Package
"myPackage" //package name
};
com.sun.tools.javadoc.Main.execute(blarg);
}
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
for(ClassDoc cDoc : classes) {
System.out.println(cDoc);
FieldDoc fields[] = cDoc.fields();
for(FieldDoc field : fields) {
System.out.println(" field: " + field);
System.out.println(" field name: " + field.name());
System.out.println(" field commentText: " + field.commentText());
System.out.println(" field type: " + field.type());
Tag[] tags = field.tags();
for(Tag tag : tags) {
System.out.println(" tag: " + tag);
System.out.println(" tag name: " + tag.name());
System.out.println(" tag text: " + tag.text());
}
}
MethodDoc methods[] = cDoc.methods();
for(MethodDoc method : methods) {
System.out.println(" method: " + method);
}
}
return true;
}
}
Is it even possible to write a doclet which generates javadoc comments in your code?
Basically, no. A doclet can't add comments to your source code because the original source code is not available to it via the doclet API. The javadoc command is designed to extract the javadoc comments from the source code and pass them to the doclet.
Or would it just be better to use my existing solution for the problem?
Possibly.
I would actually start from an existing doclet that generates HTML. I would modify it to query the database to extract the comments, and merge them with the comments in the RootDoc tree when generating the HTML.
I would not try to generate source code with extra comments added to it. But it you did want to take that approach, you would need to start with a different framework.
I need a method in my controller to call the appropriate template, from the parameters that it received, in this manner:
public static Result renderTemplate(String folder, String template) {
return ok(
views.html.<<FOLDER_GOES_HERE>>.<<TEMPLATE_NAME_GOES_HERE>>.render(Users.createForm)
);
}
if this possible? I would have done it with reflection, but for some reason I can't list the fields of view and view.html.
Can someone tell me why and explain what should I do to accomplish this?
Thank you
If you go that way you may loose type safety and the possebility to catch some error on on compile time instead of runtime.
But is still possible:
final Class<?> clazz = Class.forName("views.html." + folder + "." + template);
//assumed you have a String parameter for your template
java.lang.reflect.Method render = clazz.getDeclaredMethod("render", String.class);
play.api.templates.Html html = (play.api.templates.Html) render.invoke(null, "hi");
return ok(html);
Another way that does no include the overhead of reflection is to make an index of the templates at build time with SBT and source generators. You can walk through the views folder and then create a map from folder/template name and the invokations.
The map is in a generated class and looks like this:
map.put("folderx.templatey", views.html.folderx.templatey);//no reflection!
So at least SBT warns you at build time if the template does not exist.
I have seen the at (#) sign in Groovy files and I don't know if it's a Groovy or Java thing. I have tried to search on Google, Bing, and DuckDuckGo for the mystery at sign, but I haven't found anything. Can anyone please give me a resource to know more about what this operator does?
It's a Java annotation. Read more at that link.
As well as being a sign for an annotation, it's the Groovy Field operator
In Groovy, calling object.field calls the getField method (if one exists). If you actually want a direct reference to the field itself, you use #, ie:
class Test {
String name = 'tim'
String getName() {
"Name: $name"
}
}
def t = new Test()
println t.name // prints "Name: tim"
println t.#name // prints "tim"
'#' is an annotations in java/ Groovy look at the demo :Example with code
Java 5 and above supports the use of annotations to include metadata within programs. Groovy 1.1 and above also supports such annotations.
Annotations are used to provide information to tools and libraries.
They allow a declarative style of providing metadata information and allow it to be stored directly in the source code.
Such information would need to otherwise be provided using non-declarative means or using external files.
It can also be used to access attributes when parsing XML using Groovy's XmlSlurper:
def xml = '''<results><result index="1"/></results>'''
def results = new XmlSlurper().parseText(xml)
def index = results.result[0].#index.text() // prints "1"
http://groovy.codehaus.org/Reading+XML+using+Groovy's+XmlSlurper
I'm looking for a Java class that for a given string "the ${animal} jumped over the ${target}." is able to pull out the variable names, ie 'animal' and 'target'.
I had hoped StrSubstitutor in Commons Lang had a method
getVariables(String str) : List<String>
... but no such luck.
Yes I could write this myself, but I'm certain there must be a 3rd party library that exists out there that does this.
You could just do a simple regex match if you really just want to pull out those values and avoid the dependency of an entire library:
public List<String> getVariableNames(String source) {
List<String> vs = new ArrayList<String>();
Pattern p = Pattern.compile("\\$\\{(\\w+)\\}");
Matcher m = p.matcher(source);
while (m.find()) {
vs.add(m.group(1));
}
return vs;
}
Storing the pattern as a member variable will improve performance.
Actually I was also looking for a similar library while developing DSL Adapter for my GenericFixture.
After looking at some libraries and template based framework I eventually decided to write code by myself. Feel free to check the code I used for this purpose in DSLAdapter class from GenericFixture available on sourceforge.
The situation seems to be abnormal, but I was asked to build serializer that will parse an object into string by concatenating results of "get" methods. The values should appear in the same order as their "get" equivalent is declared in source code file.
So, for example, we have
Class testBean1{
public String getValue1(){
return "value1";
}
public String getValue2(){
return "value2";
}
}
The result should be:
"value1 - value2"
An not
"value2 - value1"
It can't be done with Class object according to the documentation. But I wonder if I can find this information in "*.class" file or is it lost? If such data exists, maybe, someone knows a ready to use tool for that purpose? If such information can't be found, please, suggest the most professional way of achieving the goal. I thought about adding some kind of custom annotations to the getters of the class that should be serialized.
If you want that you have to parse the source code, not the byte code.
There are a number of libraries that parse a source file into a node tree, my favorite is the javaparser (hosted at code.google.com), which, in a slightly modified version, is also used by spring roo.
On the usage page you can find some samples. Basically you will want to use a Visitor that listens for MethodDefinitions.
Although reflection does not anymore (as of java 7 I think) give you the methods in the order in which they appear in the source code, the class file appears to still (as of Java 8) contain the methods in the order in which they appear in the source code.
So, you can parse the class file looking for method names and then sort the methods based on the file offset in which each method was found.
If you want to do it in a less hacky way you can use Javassist, which will give you the line number of each declared method, so you can sort methods by line number.
I don't think the information is retained.
JAXB, for example, has #XmlType(propOrder="field1, field2") where you define the order of the fields when they are serialized to xml. You can implemenet something similar
Edit: This works only on concrete classes (the class to inspect has its own .class file). I changed the code below to reflect this. Until diving deeper into the ClassFileAnalyzer library to work with classes directly instead of reading them from a temporary file this limitation exists.
Following approach works for me:
Download and import following libarary ClassFileAnalyzer
Add the following two static methods (Attention! getClussDump() needs a little modification for writing out the class file to a temporary file: I removed my code here because it's very special at this point):
public static String getClassDump(Class<?> c) throws Exception {
String classFileName = c.getSimpleName() + ".class";
URL resource = c.getResource(classFileName);
if (resource == null) {
throw new RuntimeException("Works only for concreate classes!");
}
String absolutePath = ...; // write to temp file and get absolute path
ClassFile classFile = new ClassFile(absolutePath);
classFile.parse();
Info infos = new Info(classFile, absolutePath);
StringBuffer infoBuffer = infos.getInfos();
return infoBuffer.toString();
}
public static <S extends List<Method>> S sortMethodsBySourceOrder(Class<?> c, S methods) throws Exception {
String classDump = getClassDump(c);
int index = classDump.indexOf("constant_pool_count:");
final String dump = classDump.substring(index);
Collections.sort(methods, new Comparator<Method>() {
public int compare(Method o1, Method o2) {
Integer i1 = Integer.valueOf(dump.indexOf(" " + o1.getName() + lineSeparator));
Integer i2 = Integer.valueOf(dump.indexOf(" " + o2.getName() + lineSeparator));
return i1.compareTo(i2);
}});
return methods;
}
Now you can call the sortMethodsBySourceOrder with any List of methods (because sorting arrays is not very comfortable) and you will get the list back sorted.
It works by looking at the class dumps constant pool which in turn can be determined by the library.
Greetz,
GHad
Write your custom annotation to store ordering data, then use Method.getAnnotation(Class annotationClass)