| /******************************************************************************* |
| * 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); |
| } |
| |
| } |