io.smallrye.mutiny.vertx.codegen.methods.UniMethodGenerator Maven / Gradle / Ivy
The newest version!
package io.smallrye.mutiny.vertx.codegen.methods;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.vertx.AsyncResultUni;
import io.smallrye.mutiny.vertx.ReadStreamSubscriber;
import io.smallrye.mutiny.vertx.UniHelper;
import io.smallrye.mutiny.vertx.codegen.lang.CodeGenHelper;
import io.vertx.codegen.ClassModel;
import io.vertx.codegen.Helper;
import io.vertx.codegen.MethodInfo;
import io.vertx.codegen.ParamInfo;
import io.vertx.codegen.type.ClassTypeInfo;
import io.vertx.codegen.type.ParameterizedTypeInfo;
import io.vertx.codegen.type.TypeInfo;
import io.vertx.core.Handler;
import java.util.concurrent.Flow.Publisher;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static io.smallrye.mutiny.vertx.codegen.lang.TypeHelper.isConsumerOfPromise;
import static io.smallrye.mutiny.vertx.codegen.lang.TypeHelper.isHandlerOfPromise;
import static io.vertx.codegen.type.ClassKind.*;
public class UniMethodGenerator extends MutinyMethodGenerator {
private final Map> methodTypeArgMap;
public UniMethodGenerator(PrintWriter writer,
Map> methodTypeArgMap) {
super(writer);
this.methodTypeArgMap = methodTypeArgMap;
}
public void generate(ClassModel model, MethodInfo method) {
MutinyMethodDescriptor uniMethod = computeMethodInfo(method);
generateJavadoc(uniMethod);
generateMethodDeclaration(uniMethod);
generateBody(model, uniMethod);
writer.println();
}
@Override
public void generateMethodDeclaration(MutinyMethodDescriptor descriptor) {
writer.print(" @CheckReturnValue\n");
super.generateMethodDeclaration(descriptor);
}
public void generateDeclaration(MethodInfo method) {
MutinyMethodDescriptor uniMethod = computeMethodInfo(method);
generateJavadoc(uniMethod);
generateMethodDeclaration(uniMethod);
writer.println(";");
writer.println();
}
public void generateOther(MethodInfo method) {
MutinyMethodDescriptor uniMethod = computeMethodInfoOther(method);
generateJavadoc(uniMethod);
generateMethodDeclaration(uniMethod);
generateBodyOther(uniMethod);
writer.println();
}
private void generateBody(ClassModel model, MutinyMethodDescriptor descriptor) {
MethodInfo method = descriptor.getMethod();
ClassTypeInfo raw = method.getReturnType().getRaw();
String methodSimpleName = raw.getSimpleName();
String adapterType = AsyncResultUni.class.getName() + ".to" + methodSimpleName;
List params = descriptor.getOriginalMethod().getParams();
String handlerParameterName = params.get(params.size() - 1).getName();
writer.println(" { ");
writer.print(" return ");
writer.print(adapterType);
writer.println("(" + handlerParameterName + " -> {");
writer.println(" " + invokeDelegate(methodTypeArgMap, model, descriptor.getOriginalMethod()) + ";");
writer.println(" });");
writer.println(" }");
}
public static String invokeDelegate(Map> methodTypeArgMap, ClassModel model, MethodInfo method) {
StringBuilder object;
if (method.isStaticMethod()) {
object = new StringBuilder(Helper.getNonGenericType(model.getIfaceFQCN()));
} else {
object = new StringBuilder("delegate");
}
object.append(".").append(method.getName()).append("(");
int index = 0;
for (ParamInfo param : method.getParams()) {
if (index > 0) {
object.append(", ");
}
TypeInfo type = param.getType();
if (type.isParameterized() && (type.getRaw().getName().equals(Publisher.class.getName()))) {
String adapterFunction;
ParameterizedTypeInfo parameterizedType = (ParameterizedTypeInfo) type;
if (parameterizedType.getArg(0).isVariable()) {
adapterFunction = "java.util.function.Function.identity()";
} else {
adapterFunction =
"obj -> (" + parameterizedType.getArg(0).getRaw().getName() + ") obj.getDelegate()";
}
object.append(ReadStreamSubscriber.class.getName()).append(".asReadStream(")
.append(param.getName())
.append(",")
.append(adapterFunction).append(").resume()");
} else if (index < method.getParams().size() - 1 && type.isParameterized() && (type.getRaw().getName().equals(Handler.class.getName()))
&& ! (isHandlerOfPromise(param) || isConsumerOfPromise(param))) {
object.append(param.getName()).append("::accept");
} else {
object.append(CodeGenHelper.genConvParam(methodTypeArgMap, type, method, param.getName()));
}
index = index + 1;
}
object.append(")");
return object.toString();
}
private static boolean isUni(ParamInfo param) {
return param.getType().isParameterized() && param.getType().getRaw().getName().equals(Uni.class.getName());
}
private void generateBodyOther(MutinyMethodDescriptor descriptor) {
MethodInfo method = descriptor.getMethod();
writer.println(" { ");
writer.print(" return " + UniHelper.class.getName() + ".toUni(delegate.");
writer.print(method.getName());
writer.print("(");
List params = method.getParams();
writer.print(params.stream().map(pi -> {
if (pi.getType().getKind() == API) {
return pi.getName() + ".getDelegate()";
} else if (pi.getType().getKind() == FUNCTION) {
ParameterizedTypeInfo type = (ParameterizedTypeInfo) pi.getType();
TypeInfo functionParamArgType = type.getArg(0);
TypeInfo futureArgType = type.getArg(1);
if (futureArgType.getKind() == FUTURE && ((ParameterizedTypeInfo) futureArgType).getArg(0).getKind() == API) {
// Must adapt the uni to future and switch to delegate
return "\n " + pi.getName() + ".andThen(u -> " + UniHelper.class.getName() + ".toFuture(u).map(h -> h.getDelegate()))\n";
} else if (functionParamArgType.getKind() == API && futureArgType.getKind() == FUTURE) {
return "\n\t arg -> " + UniHelper.class.getName() + ".toFuture(" + pi.getName() + ".apply(" + CodeGenHelper.genTranslatedTypeName(functionParamArgType) + ".newInstance(arg)))\n";
} else {
return pi.getName();
}
} else {
return pi.getName();
}
}).collect(Collectors.joining(", ")));
TypeInfo arg = ((ParameterizedTypeInfo) (descriptor.getOriginalMethod().getReturnType())).getArg(0);
if (arg.getKind() == API) {
writer.print(").map(x -> " + arg.getSimpleName() + ".newInstance(x)));");
} else {
writer.print("));");
}
writer.println("}");
}
private MutinyMethodDescriptor computeMethodInfoOther(MethodInfo method) {
TypeInfo itemType = ((ParameterizedTypeInfo) method.getReturnType()).getArg(0);
TypeInfo uniReturnType = new io.vertx.codegen.type.ParameterizedTypeInfo(
io.vertx.codegen.type.TypeReflectionFactory.create(Uni.class).getRaw(),
true, Collections.singletonList(itemType));
MethodInfo uniMethod = method.copy().setReturnType(uniReturnType);
return new MutinyMethodDescriptor(uniMethod, method, MutinyMethodDescriptor.MutinyKind.UNI);
}
private MutinyMethodDescriptor computeMethodInfo(MethodInfo method) {
// Remove the last Handler> parameter
List params = new ArrayList<>(method.getParams());
ParamInfo handler = params.remove(method.getParams().size() - 1);
// Extract and build Uni
TypeInfo uniType = ((ParameterizedTypeInfo) ((ParameterizedTypeInfo) handler.getType()).getArg(0)).getArg(0);
TypeInfo uniUnresolvedType = ((ParameterizedTypeInfo) ((ParameterizedTypeInfo) handler.getUnresolvedType())
.getArg(0)).getArg(0);
TypeInfo uniReturnType = new io.vertx.codegen.type.ParameterizedTypeInfo(
io.vertx.codegen.type.TypeReflectionFactory.create(Uni.class).getRaw(),
uniUnresolvedType.isNullable(), Collections.singletonList(uniType));
List updatedParameters = updateParamInfoIfNeeded(params);
MethodInfo newMethod = method.copy().setReturnType(uniReturnType).setParams(updatedParameters);
return new MutinyMethodDescriptor(newMethod, method, MutinyMethodDescriptor.MutinyKind.UNI);
}
static List updateParamInfoIfNeeded(List params) {
// Check if any other parameter need to be updated (like Handler -> Consumer)
List updatedParameters = new ArrayList<>();
for (ParamInfo param : params) {
if (isHandler(param)) {
TypeInfo consumerType = ((ParameterizedTypeInfo) param.getType()).getArg(0);
TypeInfo consumerUnresolvedType = ((ParameterizedTypeInfo) param.getUnresolvedType()).getArg(0);
TypeInfo consumer = new ParameterizedTypeInfo(
io.vertx.codegen.type.TypeReflectionFactory.create(Consumer.class).getRaw(),
consumerUnresolvedType.isNullable(), Collections.singletonList(consumerType));
ParamInfo pi = new ParamInfo(param.getIndex(), param.getName(), param.getDescription(), consumer);
updatedParameters.add(pi);
} else {
updatedParameters.add(param);
}
}
return updatedParameters;
}
private static boolean isHandler(ParamInfo param) {
TypeInfo type = param.getType();
return type.isParameterized() && type.getRaw().getName().equals(Handler.class.getName());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy