CallbackReceiver.java
/*
* Copyright 2018 The Android Open Source Project
*
* 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 androidx.remotecallback.compiler;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.ArrayList;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.tools.Diagnostic;
/**
* Holder class that is created for each class instance that is a
* CallbackReceiver and has methods tagged with @RemoteCallable.
*/
public class CallbackReceiver {
private static final String RESET = "reset";
private static final String GET_METHOD = "getMethod";
private static final String GET_ARGUMENTS = "getArguments";
private static final String GET_CLS_NAME = "getClsName";
private final ProcessingEnvironment mEnv;
private final Element mElement;
private final String mClsName;
private final ArrayList<CallableMethod> mMethods = new ArrayList<>();
private final Messager mMessager;
public CallbackReceiver(Element c, ProcessingEnvironment env,
Messager messager) {
mEnv = env;
mElement = c;
mClsName = c.toString();
mMessager = messager;
}
/**
* Adds a method tagged with @RemoteCallable to this receiver.
*/
public void addMethod(Element element) {
for (CallableMethod method: mMethods) {
if (method.getName().equals(element.getSimpleName().toString())) {
mMessager.printMessage(Diagnostic.Kind.ERROR,
"Multiple methods named " + element.getSimpleName());
return;
}
}
mMethods.add(new CallableMethod(mClsName, element, mEnv));
}
/**
* Generates the code to handle creating and executing callbacks. The code
* is assembled in one class that implements runnable that when run,
* registers all of the CallbackHandlers.
*/
public void finish(ProcessingEnvironment env, Messager messager) {
if (mMethods.size() == 0) {
messager.printMessage(Diagnostic.Kind.ERROR, "No methods found for " + mClsName);
return;
}
TypeSpec.Builder genClass = TypeSpec
.classBuilder(findInitClass(mElement))
.superclass(TypeName.get(mElement.asType()))
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder runBuilder = MethodSpec
.constructorBuilder()
.addModifiers(Modifier.PUBLIC);
for (CallableMethod method: mMethods) {
method.addMethods(genClass, runBuilder, env, messager);
}
genClass.addMethod(runBuilder.build());
try {
TypeSpec typeSpec = genClass.build();
String pkg = getPkg(mElement);
JavaFile.builder(pkg, typeSpec)
.build()
.writeTo(mEnv.getFiler());
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR, "Exception writing " + e);
}
}
private String findInitClass(Element element) {
return String.format("%sInitializer", element.getSimpleName());
}
private String getPkg(Element s) {
String pkg = mEnv.getElementUtils().getPackageOf(s).toString();
return pkg;
}
}