Can I generate Javadoc comments with the help of a custom doclet? - java

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.

Related

How to get #param text in Java? [duplicate]

in my program I dynamically get the name of the .java file. In this file I need to find all methods, foreach method also all parameters (also with their annotations).
I read through the discussions here and found this https://code.google.com/p/javaparser/ javaparser, that seems pretty easy to use, but the problem is, that it is just for 1.5.
Than you mentioned, that Java 1.6 has already got built-in parser (javax.lang.model). But I can not figure out, how it works. Do you know any good tutorial/example of it?
Do you know any other way to parse java source file?
How about using Doclet API?
Normally, This API is used from bat file, but you can invoke programmatically like the following.
IMPORTANT: This API exists in not rt.jar(JRE) but tools.jar (JDK). So you need to add tool.jar into classpath.
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.Doclet;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.RootDoc;
import com.sun.tools.javadoc.Main;
public class DocletTest {
public static void main(String[] args) {
Main.execute("", Analyzer.class.getName(), new String[] {"path/to/your/file.java"});
}
public static class Analyzer extends Doclet {
public static boolean start(RootDoc root) {
for (ClassDoc classDoc : root.classes()) {
System.out.println("Class: " + classDoc.qualifiedName());
for (MethodDoc methodDoc : classDoc.methods()) {
System.out.println(" " + methodDoc.returnType() + " " + methodDoc.name() + methodDoc.signature());
}
}
return false;
}
}
}
Take another look at the javaparser project. It has been updated to support all modern Java versions.
The Doclet API is really hard to use and is badly documented. It will be either going away or be replaced with something better, hopefully even in Java 1.9.

GATE usage in java Netbeans

I am trying to write an application from extracting entities from a text and want to use GATE jar files. For which I have installed the GATE tool and have imported jar files, but it is giving errors. I can't understand from where to download more jar files and how to run the first simple program with this.
Please make sure that you added gate.jar from YOUR_GATE_HOME/bin folder.
From your screenshot I can assume that you used an example provided by GitHub. This example looks good, except one part (from my point of view of course). I would suggest to replace output piece with the next more readable code:
String text = "Steve works for Apple Inc in California.";
Document gateDocument = Factory.newDocument(text);
corpus.add(gateDocument);
// tell the ANNIE application about the corpus and run it
annie.setCorpus(corpus);
annie.execute();
List<Annotation> personAnnotations = gateDocument.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).inDocumentOrder();
for (Annotation personAnnotation : personAnnotations) {
System.out.println("Entity Text: " + gate.Utils.stringFor(gateDocument, personAnnotation) + " Features: " + personAnnotation.getFeatures());
}
Similar things could be done for Location, Organisation and other Entity types defined in GATE. Also do not forget to release resources with Factory.deleteResource().

How to implement a 'generate getter/setter' for a Java Class in emacs?

Sometimes I miss the laziness of using an IDE that let me just write the attribute of a Java class and then let the IDE generate the required getter/setter.
Can Emacs do this?
Currently I just copy paste a pair of getter/setter form the previous line, and then copy paste and modify it. It's simple, but yet, make coding a little bit funnier :)
You asked specifically about generating a getter/setter pair. And you can write elisp to do this. But it may be interesting to look into a more general solution.
To solve this generally, I use ya-snippet . The name refers to "Yet Another Snippet package", so you can be sure the problem has been solved before. But I found ya-snippet to be the most useful, simple, and capable solution, for my needs.
For a property with a getter/setter, I type
prop<TAB>
...and I get a template that I can then fill in, like a form. I specify the name of the property, and everything else is generated. Very nice, easy.
This works for any micro-pattern you commonly use in code. I have snippets for a singleton, constructor, for loops, switch statements, try/catch, and so on.
The key with ya-snippet is there is no elisp code to write. Basically I just provide the text for the template, and it works. This is the ya-snippet code for the getter/setter snippet you see above:
# name : getter/setter property ... { ... }
# key: prop
# --
private ${1:Type} _${2:Name};
public ${1:Type} get$2 {
${3://get impl}
}
public void set$2($1 value) {
${4://set impl}
}
Everything above the "# --" is metadata for the snip. The "key" is the most important bit of that metadata - it is the short sequence that can be expanded. The name is shown on the yasnippet menu. The stuff below the # -- line is the expansion code. It includes several fill-in fields.
YAsnippet works for any programming mode in emacs (java, php, c#, python, etc) and it works for other text modes too.
I'm using yasnippet as well, but this is a better snippet, imho:
# -*- mode: snippet -*-
# name: property
# key: r
# --
private ${1:T} ${2:value};
public $1 get${2:$(capitalize text)}() { return $2; }
public void set${2:$(capitalize text)}($1 $2) { this.$2 = $2; }
$0
This code, for instance is generated in 10 keystrokes (r, C-o, Long, C-o, id, C-o):
private Long id;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
I recommend binding yas/expand to C-o and not TAB to avoid clashes with
e.g. auto-complete.
I have this setup:
(global-set-key "\C-o" 'open-line-or-yas)
(defun open-line-or-yas ()
(interactive)
(cond ((and (looking-back " ") (looking-at "[\s\n}]+"))
(insert "\n\n")
(indent-according-to-mode)
(previous-line)
(indent-according-to-mode))
((expand-abbrev))
(t
(setq *yas-invokation-point* (point))
(yas/next-field-or-maybe-expand-1))))
(defun yas/next-field-or-maybe-expand-1 ()
(interactive)
(let ((yas/fallback-behavior 'return-nil))
(unless (yas/expand)
(yas/next-field))))
Note (expand-abbrev) somewhere inside this code. It allows me to expand e.g. bis to BufferedInputStream when I define:
(define-abbrev-table 'java-mode-abbrev-table
'(
("bb" "ByteBuffer" nil 1)
("bis" "BufferedInputStream" nil 1)
%...
))
This site shows with elisp that can be pasted into your .emacs, how to generate getter and setter methods.
JDEE has the capability along with a lots more built in to itself.
If you use the java-mode YASnippets by nekop you get the snippet prop which lets you define a private variable and it automatically makes a getter and a setter for that variable. The snippet reads as follows:
# -*- mode: snippet -*-
# name: property
# key: prop
# --
private ${1:String} ${2:name};$0
public $1 get${2:$(upcase-initials text)}() {
return $2;
}
public void set${2:$(upcase-initials text)}($1 $2) {
this.$2 = $2;
}
As can be seen this snippet does not differ much from the other answers except that it may be better formatted. Another advantage is that it is part of a package of snippets for Java.

Get declared methods in order they appear in source code

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)

A Java API to generate Java source files [closed]

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/

Categories