blob: b8ba42c49eac249235e93dfb6dec0bc92fbe594b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Composent, Inc. and others. All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Composent, Inc. - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.internal.remoteservice.apt.java6;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaFileObject;
import org.eclipse.ecf.internal.remoteservice.apt.java6.JavaFormatter.AccessSpecifier;
import org.eclipse.ecf.remoteservice.AsyncService;
import org.eclipse.ecf.remoteservice.IAsyncRemoteServiceProxy;
@SupportedAnnotationTypes({ "org.eclipse.ecf.remoteservice.AsyncService" })
public class AsyncAnnotationProcessor extends AbstractProcessor {
@SuppressWarnings("restriction")
private static final String FUTURE_PACKAGE_IMPORT = org.eclipse.equinox.concurrent.future.IFuture.class.getName();
private static final String REMOTESERVICE_PACKAGE_IMPORT = org.eclipse.ecf.remoteservice.IAsyncCallback.class.getName();
public AsyncAnnotationProcessor() {
super();
}
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
ProcessingEnvironment env = super.processingEnv;
Filer filer = env.getFiler();
Set<TypeElement> annotatedDecls = (Set<TypeElement>) roundEnv.getElementsAnnotatedWith(AsyncService.class);
for(Iterator<TypeElement> i = annotatedDecls.iterator(); i.hasNext(); ) {
writeAsyncType(filer,i.next());
}
return true;
}
private void writeAsyncType(Filer filer, TypeElement te) {
String qualifiedAsyncName = te.getQualifiedName().toString()+IAsyncRemoteServiceProxy.ASYNC_INTERFACE_SUFFIX;
String simpleAsyncName = te.getSimpleName().toString()+IAsyncRemoteServiceProxy.ASYNC_INTERFACE_SUFFIX;
int lastDot = qualifiedAsyncName.lastIndexOf(".");
String packageAsyncName = null;
if (lastDot > 0) {
packageAsyncName = qualifiedAsyncName.substring(0,lastDot);
}
JavaFileObject javaFile = null;
try {
javaFile = filer.createSourceFile(qualifiedAsyncName, (Element[]) null);
Writer writer = javaFile.openWriter();
PrintWriter pw = new PrintWriter(writer);
JavaFormatter formatter = new JavaFormatter(pw);
if (packageAsyncName != null) {
formatter.printPackage(packageAsyncName);
pw.println();
}
formatter.printImport(FUTURE_PACKAGE_IMPORT);
formatter.printImport(REMOTESERVICE_PACKAGE_IMPORT);
pw.println();
formatter.printText("@SuppressWarnings(\"restriction\")");
formatter.openInterface(AccessSpecifier.PUBLIC, simpleAsyncName, new String[] { IAsyncRemoteServiceProxy.class.getName() });
pw.println();
writeAsyncMethods(filer, te, (List<ExecutableElement>) te.getEnclosedElements(), formatter);
pw.println();
formatter.closeElement();
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeAsyncMethods(Filer filer, TypeElement te,
List<ExecutableElement> list, JavaFormatter formatter) {
for(Iterator<ExecutableElement> i = list.iterator(); i.hasNext(); ) {
ExecutableElement elem = i.next();
writeAsyncMethodCallback(elem, formatter);
writeAsyncMethodFuture(elem, formatter);
}
}
private void writeAsyncMethodCallback(ExecutableElement methodDecl,
JavaFormatter formatter) {
String resultType = getResultTypeForExecutableElement(methodDecl);
List<VariableElement> methodParams = (List<VariableElement>) methodDecl.getParameters();
List ptypes = new ArrayList();
List ps = new ArrayList();
for(Iterator<VariableElement> i=methodParams.iterator(); i.hasNext(); ) {
VariableElement m = i.next();
TypeMirror tm = m.asType();
ptypes.add(tm.toString());
ps.add(m.getSimpleName().toString());
}
final String asyncCallbackClassname = "IAsyncCallback";
if (resultType == null) {
ptypes.add(asyncCallbackClassname+"<Void>");
} else {
ptypes.add(asyncCallbackClassname+"<"+resultType+">");
}
ps.add("callback");
formatter.openMethod(false, AccessSpecifier.PUBLIC, null, methodDecl.getSimpleName()+IAsyncRemoteServiceProxy.ASYNC_METHOD_SUFFIX, (String[]) ptypes.toArray(new String[] {}), (String[]) ps.toArray(new String[] {}), false);
}
private String getBoxedTypeNameForTypeMirror(TypeMirror resultType) {
if (resultType == null) return null;
if (resultType instanceof ArrayType) {
ArrayType at = (ArrayType) resultType;
String boxedType = getBoxedTypeNameForTypeMirror(at.getComponentType());
if (boxedType == null) return null;
return boxedType+"[]";
}
TypeKind type = resultType.getKind();
if (type == null) return null;
if (type.equals(TypeKind.BOOLEAN)) {
return "Boolean";
} else if (type.equals(TypeKind.BYTE)) {
return "Byte";
} else if (type.equals(TypeKind.CHAR)) {
return "Character";
} else if (type.equals(TypeKind.DOUBLE)) {
return "Double";
} else if (type.equals(TypeKind.FLOAT)) {
return "Float";
} else if (type.equals(TypeKind.INT)) {
return "Integer";
} else if (type.equals(TypeKind.LONG)) {
return "Long";
} else if (type.equals(TypeKind.SHORT)) {
return "Short";
} else if (type.equals(TypeKind.VOID)) {
return "Void";
} else if (type.equals(TypeKind.DECLARED)) {
return resultType.toString();
}
return null;
}
private String getResultTypeForExecutableElement(ExecutableElement methodDecl) {
if (methodDecl == null) return null;
TypeMirror returnType = methodDecl.getReturnType();
if (returnType == null) return null;
return getBoxedTypeNameForTypeMirror(returnType);
}
private void writeAsyncMethodFuture(ExecutableElement methodDecl,
JavaFormatter formatter) {
List<VariableElement> methodParams = (List<VariableElement>) methodDecl.getParameters();
List ptypes = new ArrayList();
List ps = new ArrayList();
for(Iterator<VariableElement> i=methodParams.iterator(); i.hasNext(); ) {
VariableElement m = i.next();
TypeMirror tm = m.asType();
ptypes.add(tm.toString());
ps.add(m.getSimpleName().toString());
}
formatter.printText("@SuppressWarnings(\"rawtypes\")");
formatter.openMethod(false, AccessSpecifier.PUBLIC, "IFuture", methodDecl.getSimpleName()+IAsyncRemoteServiceProxy.ASYNC_METHOD_SUFFIX, (String[]) ptypes.toArray(new String[] {}), (String[]) ps.toArray(new String[] {}), false);
}
}