package net.sourceforge.jannotater;
import static com.sun.mirror.util.DeclarationVisitors.NO_OP;
import static com.sun.mirror.util.DeclarationVisitors.getDeclarationScanner;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Filer.Location;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.ConstructorDeclaration;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.ParameterDeclaration;
import com.sun.mirror.type.ArrayType;
import com.sun.mirror.type.PrimitiveType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.type.VoidType;
import com.sun.mirror.util.SimpleDeclarationVisitor;
public class AnnotateRProcessor extends SimpleDeclarationVisitor implements AnnotationProcessor {
private final AnnotationProcessorEnvironment mEnv;
private final Set<AnnotationTypeDeclaration> mAnnotationDeclarations;
HashMap<String, Writer> inputOutputMap = new HashMap<String, Writer>();
ArrayList<String> toExport = new ArrayList<String>();
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
AnnotateRProcessor(Set<AnnotationTypeDeclaration> annotationDeclarations, AnnotationProcessorEnvironment env) {
this.mAnnotationDeclarations = annotationDeclarations;
this.mEnv = env;
}
public void process() {
for (AnnotationTypeDeclaration annotationType : this.mAnnotationDeclarations) {
for (Declaration typeDecl : mEnv.getDeclarationsAnnotatedWith(annotationType)) {
//env.getSpecifiedTypeDeclarations())
System.out.println("accepting: " + typeDecl.toString());
String filename = typeDecl.getPosition().file().getName();
Writer output = this.inputOutputMap.get(filename);
if (output == null) {
try {
output = this.mEnv.getFiler().createTextFile(Location.SOURCE_TREE, "R",//((MemberDeclaration) typeDecl).getDeclaringType().getPackage().getQualifiedName(),
new File(filename.substring(0, filename.lastIndexOf('.')) + ".R"), null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.inputOutputMap.put(filename, output);
}
typeDecl.accept(getDeclarationScanner(this, NO_OP));
}
}
try {
Writer output = this.mEnv.getFiler().createTextFile(Location.SOURCE_TREE, "",//((MemberDeclaration) typeDecl).getDeclaringType().getPackage().getQualifiedName(),
new File("NAMESPACE"), null);
output.write("import(\"rJava\")\n");
if (this.toExport.size() > 0) {
int i = 0;
output.write("export(\"" + toExport.get(i) + "\"");
for (i++; i < toExport.size(); i++) {
output.write(", \"" + toExport.get(i) + "\"");
}
output.write(")\n");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void visitMethodDeclaration(MethodDeclaration d) {
try {
String filename = d.getPosition().file().getName();
Writer output = this.inputOutputMap.get(filename);
this.toExport.add(d.getSimpleName());
output.write("" + d.getSimpleName() + " <- function\n");
String javadoc = d.getDocComment();
if (javadoc == null) {
output.write("### TODO:Function documentation\n");
} else {
output.write("### " + javadoc.replaceAll(LINE_SEPARATOR, LINE_SEPARATOR + "### ") + "\n");
}
output.write("(object");
if (d.getParameters().size() > 0) {
output.write(", ");
}
output.write("\n### object of type " + d.getDeclaringType().toString() + " to be operated on\n");
writeParameters(d.getParameters(), output, true);
output.write(") {\n");
output.write(" .jcall(object, ");
output.write("\"" + typeToRAbbreviation(d.getReturnType()) + "\", ");
output.write("\"" + d.getSimpleName() + "\"");
if (d.getParameters().size() > 0) {
output.write(", ");
}
writeParameters(d.getParameters(), output, false);
output.write(")\n}\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String typeToRAbbreviation(TypeMirror type) {
if (type instanceof PrimitiveType) {
switch (((PrimitiveType) type).getKind()) {
case BOOLEAN:
return "Z";
case BYTE:
return "B";
case CHAR:
return "C";
case DOUBLE:
return "D";
case FLOAT:
return "F";
case INT:
return "I";
case LONG:
return "J";
}
}
if (type instanceof VoidType) {
return "V";
} else if (type.toString().equals("java.lang.String")) {
return "S";
} else if (type instanceof ArrayType) {
return "[" + typeToRAbbreviation(((ArrayType) type).getComponentType());
}
return "L" + type.toString();
}
@Override
public void visitConstructorDeclaration(ConstructorDeclaration d) {
try {
String filename = d.getPosition().file().getName();
Writer output = this.inputOutputMap.get(filename);
this.toExport.add("new" + d.getSimpleName());
output.write("new" + d.getSimpleName() + " <- function\n");
String javadoc = d.getDocComment();
if (javadoc == null) {
output.write("### TODO:Function documentation\n");
} else {
output.write("### " + javadoc.replaceAll(LINE_SEPARATOR, LINE_SEPARATOR + "### ") + "\n");
}
output.write("(");
writeParameters(d.getParameters(), output, true);
output.write(") {\n");
output.write(" .jnew(\"" + d.getDeclaringType().getQualifiedName() + "\"");
if (d.getParameters().size() > 0) {
output.write(", ");
}
writeParameters(d.getParameters(), output, false);
output.write(")\n}\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeParameters(Collection<ParameterDeclaration> parameters, Writer output, boolean inlineComments)
throws IOException {
boolean first = true;
Iterator<ParameterDeclaration> paramIter = parameters.iterator();
while (paramIter.hasNext()) {
ParameterDeclaration parameter = paramIter.next();
output.write(parameter.getSimpleName());
if (paramIter.hasNext())
output.write(", ");
if (inlineComments) {
output.write("\n### converted to a Java " + parameter.getType().toString() + "\n");
}
first = false;
}
}
}