import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.TypeTags;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.List;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;
/**
* Created with IntelliJ IDEA.
* User: irakov
* Date: 15.05.14
* Time: 18:15
*/
@SupportedAnnotationTypes(value = {AutoExternalizableProcessor.ANNOTATION_TYPE})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class AutoExternalizableProcessor extends AbstractProcessor {
public static final String ANNOTATION_TYPE = "AutoExternalizable";
private JavacProcessingEnvironment javacProcessingEnv;
private TreeMaker maker;
@Override
public void init(ProcessingEnvironment procEnv) {
super.init(procEnv);
this.javacProcessingEnv = (JavacProcessingEnvironment) procEnv;
this.maker = TreeMaker.instance(javacProcessingEnv.getContext());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (annotations == null || annotations.isEmpty()) {
return false;
}
final TypeElement annotation = javacProcessingEnv.getElementUtils().getTypeElement(ANNOTATION_TYPE);
if (annotation != null) {
final Set<? extends Element> classes = roundEnv.getElementsAnnotatedWith(annotation);
JavacElements utils = javacProcessingEnv.getElementUtils();
for (final Element e : classes) {
JCTree classNode = utils.getTree(e);
JCTree.JCClassDecl classDecl = (JCTree.JCClassDecl)classNode;
JCTree.JCExpression serializableInterface = maker.Ident(utils.getName("java"));
serializableInterface = maker.Select(serializableInterface, utils.getName("io"));
serializableInterface = maker.Select(serializableInterface, utils.getName("Externalizable"));
JCTree.JCExpression ioExceptionClass = maker.Ident(utils.getName("java"));
ioExceptionClass = maker.Select(ioExceptionClass, utils.getName("io"));
ioExceptionClass = maker.Select(ioExceptionClass, utils.getName("IOException"));
JCTree.JCExpression classNotFoundExceptionClass = maker.Ident(utils.getName("java"));
classNotFoundExceptionClass = maker.Select(classNotFoundExceptionClass, utils.getName("lang"));
classNotFoundExceptionClass = maker.Select(classNotFoundExceptionClass, utils.getName("ClassNotFoundException"));
classDecl.implementing = classDecl.implementing.append(serializableInterface);
JCTree.JCAnnotation overrideAnnotaion = maker.Annotation(maker.Ident(utils.getName("Override")), List.<JCTree.JCExpression>nil());
JCTree.JCModifiers methodModifiers = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotaion));
JCTree.JCExpression objectOutputClass = maker.Ident(utils.getName("java"));
objectOutputClass = maker.Select(objectOutputClass, utils.getName("io"));
objectOutputClass = maker.Select(objectOutputClass, utils.getName("ObjectOutput"));
JCTree.JCExpression objectInputClass = maker.Ident(utils.getName("java"));
objectInputClass = maker.Select(objectInputClass, utils.getName("io"));
objectInputClass = maker.Select(objectInputClass, utils.getName("ObjectInput"));
JCTree.JCBlock writeExternalBlock = maker.Block(0, List.<JCTree.JCStatement>nil());
JCTree.JCMethodDecl writeExternalMethod = maker.MethodDef(
methodModifiers,
utils.getName("writeExternal"),
maker.TypeIdent(TypeTags.VOID),
List.<JCTree.JCTypeParameter>nil(),
List.of(maker.VarDef(maker.Modifiers(0), utils.getName("out"), objectOutputClass, null)),
List.of(ioExceptionClass),
writeExternalBlock,
null
);
JCTree.JCBlock readExternalBlock = maker.Block(0, List.<JCTree.JCStatement>nil());
JCTree.JCMethodDecl readExternalMethod = maker.MethodDef(
methodModifiers,
utils.getName("readExternal"),
maker.TypeIdent(TypeTags.VOID),
List.<JCTree.JCTypeParameter>nil(),
List.of(maker.VarDef(maker.Modifiers(0), utils.getName("in"), objectInputClass, null)),
List.of(ioExceptionClass, classNotFoundExceptionClass),
readExternalBlock,
null
);
classDecl.defs = classDecl.defs.append(writeExternalMethod);
classDecl.defs = classDecl.defs.append(readExternalMethod);
for (JCTree t : classDecl.implementing) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, t.getClass() + t.toString());
}
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, classDecl.toString());
}
return true;
}
return false;
}
}