com.github.longdt.vertxservice.processor.ServiceProxyHandlerWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vertx-service4j Show documentation
Show all versions of vertx-service4j Show documentation
A lightweight replacement for vertx-service-proxy. This library is highly optimized for vertx java
package com.github.longdt.vertxservice.processor;
import com.github.longdt.vertxservice.util.Arguments;
import com.squareup.javapoet.*;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.Message;
import io.vertx.serviceproxy.HelperUtils;
import io.vertx.serviceproxy.ServiceException;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.io.IOException;
import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotationSpec;
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static javax.lang.model.element.Modifier.PUBLIC;
public class ServiceProxyHandlerWriter {
private final Filer filer;
private final Elements elements;
private final SourceVersion sourceVersion;
private final Types types;
ServiceProxyHandlerWriter(ProcessingEnvironment processingEnv) {
this.filer = processingEnv.getFiler();
this.elements = processingEnv.getElementUtils();
this.sourceVersion = processingEnv.getSourceVersion();
this.types = processingEnv.getTypeUtils();
}
void writeServiceProxyHandler(ServiceDeclaration serviceDeclaration) throws IOException {
String serviceProxy = serviceDeclaration.target().getSimpleName().toString() + Constant.PROXY_HANDLER;
TypeSpec.Builder builder =
classBuilder(serviceProxy)
.addOriginatingElement(serviceDeclaration.target());
generatedAnnotationSpec(
elements,
sourceVersion,
Service4JProcessor.class,
"Do not edit this file")
.ifPresent(builder::addAnnotation);
builder.addModifiers(Modifier.PUBLIC);
addSuperinterface(builder);
addFields(builder, serviceDeclaration);
addConstructor(builder, serviceDeclaration);
addMethods(builder, serviceDeclaration);
JavaFile.builder(elements.getPackageOf(serviceDeclaration.target()).getQualifiedName().toString(), builder.build())
.skipJavaLangImports(true)
.build()
.writeTo(filer);
}
private void addMethods(TypeSpec.Builder builder, ServiceDeclaration serviceDeclaration) {
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("handle")
.addParameter(ParameterizedTypeName.get(Message.class, Object.class), Constant.MESSAGE_VARIABLE)
.addModifiers(PUBLIC)
.addAnnotation(Override.class)
.returns(void.class);
CodeBlock.Builder codeBlockBuilder = CodeBlock.builder();
codeBlockBuilder.beginControlFlow("try");
codeBlockBuilder.addStatement("var $1L = $2L.headers().get($1S)", Constant.ACTION, Constant.MESSAGE_VARIABLE);
codeBlockBuilder.beginControlFlow("if ($L == null)", Constant.ACTION)
.addStatement("throw new $T(\"action not specified\")", IllegalStateException.class)
.endControlFlow();
codeBlockBuilder.beginControlFlow("switch ($L)", Constant.ACTION);
serviceDeclaration.methods().forEach(e -> addCase(codeBlockBuilder, e));
codeBlockBuilder.beginControlFlow("default:")
.addStatement("throw new $T(\"Invalid action: \" + $L)", IllegalStateException.class, Constant.ACTION)
.endControlFlow();
codeBlockBuilder.endControlFlow();
codeBlockBuilder.nextControlFlow("catch ($T e)", Exception.class);
codeBlockBuilder.beginControlFlow("if ($L)", Constant.INCLUDE_DEBUG_INFO_VARIABLE)
.addStatement("$L.reply(new $T(500, e.getMessage(), $T.generateDebugInfo(e)))", Constant.MESSAGE_VARIABLE, ServiceException.class, HelperUtils.class)
.nextControlFlow("else")
.addStatement("$L.reply(new $T(500, e.getMessage()))", Constant.MESSAGE_VARIABLE, ServiceException.class)
.endControlFlow();
codeBlockBuilder.endControlFlow();
methodBuilder.addCode(codeBlockBuilder.build());
builder.addMethod(methodBuilder.build());
}
private void addCase(CodeBlock.Builder codeBlockBuilder, ExecutableElement element) {
var params = element.getParameters();
if (params.isEmpty()) {
new NoParamMethodProxyHandlerWriter(types).writeInvocation(codeBlockBuilder, element);
} else if (params.size() == 1) {
new SingleParamMethodProxyHandlerWriter(types).writeInvocation(codeBlockBuilder, element);
} else {
new MultiParamMethodProxyHandlerWriter(types).writeInvocation(codeBlockBuilder, element);
}
}
private void addConstructor(TypeSpec.Builder builder, ServiceDeclaration serviceDeclaration) {
MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
constructor.addModifiers(PUBLIC);
constructor.addParameter(TypeName.get(Vertx.class), Constant.VERTX_VARIABLE);
constructor.addParameter(TypeName.get(serviceDeclaration.target().asType()), Constant.SERVICE_VARIABLE);
constructor.addParameter(TypeName.get(boolean.class), Constant.INCLUDE_DEBUG_INFO_VARIABLE);
constructor.addStatement("this.$1L = $1L", Constant.VERTX_VARIABLE);
constructor.addStatement("this.$1L = $1L", Constant.SERVICE_VARIABLE);
constructor.addStatement("this.$1L = $1L", Constant.INCLUDE_DEBUG_INFO_VARIABLE);
builder.addMethod(constructor.build());
}
private void addFields(TypeSpec.Builder builder, ServiceDeclaration serviceDeclaration) {
builder.addField(
FieldSpec.builder(Vertx.class, Constant.VERTX_VARIABLE, Modifier.PRIVATE, Modifier.FINAL)
.build());
builder.addField(
FieldSpec.builder(TypeName.get(serviceDeclaration.target().asType()), Constant.SERVICE_VARIABLE, Modifier.PRIVATE, Modifier.FINAL)
.build());
builder.addField(
FieldSpec.builder(boolean.class, Constant.INCLUDE_DEBUG_INFO_VARIABLE, Modifier.PRIVATE, Modifier.FINAL)
.build());
}
private void addSuperinterface(TypeSpec.Builder builder) {
builder.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(Handler.class),
ParameterizedTypeName.get(Message.class, Object.class)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy