/* * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.arialyy.compiler; import com.arialyy.annotations.Download; import com.arialyy.annotations.Upload; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeSpec; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.annotation.processing.Filer; import javax.lang.model.element.Modifier; /** * Created by lyy on 2017/9/6. * 任务事件代理文件 * *
 *   
 * package com.arialyy.simple.download;
 *
 * import com.arialyy.aria.core.download.DownloadTask;
 * import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
 *
 * public final class SingleTaskActivity$$DownloadListenerProxy extends
 * AbsSchedulerListener {
 * private SingleTaskActivity obj;
 *
 *    public void onPre(final DownloadTask task) {
 *      obj.onPre((DownloadTask)task);
 *    }
 *
 *    public void onTaskStart(final DownloadTask task) {
 *      obj.onStart((DownloadTask)task);
 *    }
 *
 *    public void setListener(final Object obj) {
 *      this.obj = (SingleTaskActivity)obj;
 *    }
 * }
 *   
 * 
*/ final class EventProxyFiler { private Filer mFiler; private ParamObtainUtil mPbUtil; EventProxyFiler(Filer filer, ParamObtainUtil pbUtil) { mFiler = filer; mPbUtil = pbUtil; } /** * 创建任务事件代理文件 */ void createEventProxyFile() throws IOException { Map map = mPbUtil.getMethodParams(); Set keys = mPbUtil.getMethodParams().keySet(); for (String key : keys) { //if (key.equals( // "com.arialyy.simple.download.SingleTaskActivity$$DownloadGroupListenerProxy")) { // // ProxyClassParam entity = mPbUtil.getMethodParams().get(key); // JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build(); // createFile(jf); //} ProxyClassParam entity = mPbUtil.getMethodParams().get(key); JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build(); createFile(jf); } } /** * 创建代理方法 * * @param taskEnum 任务类型枚举{@link TaskEnum} * @param annotation {@link Download}、{@link Upload} * @param methodName 被代理类注解的方法名 */ private MethodSpec createProxyMethod(TaskEnum taskEnum, Class annotation, String methodName) { ClassName task = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); ParameterSpec taskParam = ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build(); String callCode; if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { callCode = "task, subEntity"; } else { callCode = "task"; } StringBuilder sb = new StringBuilder(); sb.append("Set keys = keyMapping.get(\"").append(methodName).append("\");\n"); sb.append("if (keys != null) {\n\tif (keys.contains(task.getKey())) {\n") .append("\t\tobj.") .append(methodName) .append("((") .append(taskEnum.getClassName()) .append(")") .append(callCode) .append(");\n\t}\n} else {\n") .append("\tobj.") .append(methodName) .append("((") .append(taskEnum.getClassName()) .append(")") .append(callCode) .append(");\n}\n"); MethodSpec.Builder builder = MethodSpec.methodBuilder(annotation.getSimpleName()) .addModifiers(Modifier.PUBLIC) .returns(void.class) .addParameter(taskParam) .addAnnotation(Override.class) .addCode(sb.toString()); //任务组接口 if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { ClassName subTask = ClassName.get(TaskEnum.DOWNLOAD_ENTITY.pkg, TaskEnum.DOWNLOAD_ENTITY.className); ParameterSpec subTaskParam = ParameterSpec.builder(subTask, "subEntity").addModifiers(Modifier.FINAL).build(); builder.addParameter(subTaskParam); } //PrintLog.getInstance().info(builder.build().toString()); return builder.build(); } /** * 创建代理类 */ private TypeSpec createProxyClass(ProxyClassParam entity) { TypeSpec.Builder builder = TypeSpec.classBuilder(entity.proxyClassName).addModifiers(Modifier.PUBLIC, Modifier.FINAL); //添加被代理的类的字段 ClassName obj = ClassName.get(entity.packageName, entity.className); FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build(); builder.addField(observerField); //添加url映射表 FieldSpec mappingField = FieldSpec.builder( ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), "keyMapping").addModifiers(Modifier.PRIVATE).initializer("new $T()", HashMap.class).build(); builder.addField(mappingField); //添加注解方法 for (TaskEnum te : entity.methods.keySet()) { Map, String> temp = entity.methods.get(te); if (temp != null) { for (Class annotation : temp.keySet()) { MethodSpec method = createProxyMethod(te, annotation, temp.get(annotation)); builder.addMethod(method); } } } //增加构造函数 CodeBlock.Builder cb = CodeBlock.builder(); cb.add("Set set = null;\n"); for (String methodName : entity.keyMappings.keySet()) { //PrintLog.getInstance().info("methodName ====> " + methodName); Set keys = entity.keyMappings.get(methodName); if (keys == null || keys.size() == 0) continue; StringBuilder sb = new StringBuilder(); sb.append("set = new $T();\n"); for (String key : keys) { if (key.isEmpty()) continue; sb.append("set.add(\"").append(key).append("\");\n"); } sb.append("keyMapping.put(\"").append(methodName).append("\", ").append("set);\n"); cb.add(sb.toString(), ClassName.get(HashSet.class)); } MethodSpec structure = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); builder.addMethod(structure); //添加设置代理的类 ParameterSpec parameterSpec = ParameterSpec.builder(Object.class, "obj").addModifiers(Modifier.FINAL).build(); MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER) .addModifiers(Modifier.PUBLIC) .returns(void.class) .addParameter(parameterSpec) .addAnnotation(Override.class) .addCode("this.obj = (" + entity.className + ")obj;\n") .build(); builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n"); //创建父类参数 ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener"); //主任务泛型参数 ClassName taskTypeVariable = ClassName.get(entity.mainTaskEnum.pkg, entity.mainTaskEnum.className); //子任务泛型参数 ClassName subTaskTypeVariable = ClassName.get(entity.subTaskEnum.pkg, entity.subTaskEnum.className); builder.superclass( ParameterizedTypeName.get(superClass, taskTypeVariable, subTaskTypeVariable)); builder.addMethod(listener); return builder.build(); } private void createFile(JavaFile jf) throws IOException { if (ProxyConstance.DEBUG) { // 如果需要在控制台打印生成的文件,则去掉下面的注释 jf.writeTo(System.out); } else { jf.writeTo(mFiler); } } }