Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC async lambda #198

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 66 additions & 11 deletions rx-gen/src/main/java/io/vertx/lang/rx/AbstractRxGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
import io.vertx.codegen.doc.Tag;
import io.vertx.codegen.doc.Token;
import io.vertx.codegen.type.*;
import io.vertx.core.Handler;

import javax.lang.model.element.Element;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

import static io.vertx.codegen.type.ClassKind.*;
import static java.util.stream.Collectors.joining;
Expand Down Expand Up @@ -510,12 +513,24 @@ protected void startMethodTemplate(ClassTypeInfo type, MethodInfo method, String
writer.print(" ");
writer.print(method.getName());
writer.print("(");
writer.print(method.getParams().stream().map(it -> genTypeName(it.getType()) + " " + it.getName()).collect(joining(", ")));
writer.print(method.getParams().stream().map(it -> genTypeNameMethodParam(it.getType()) + " " + it.getName()).collect(joining(", ")));
writer.print(")");

}

protected final String genTypeName(TypeInfo type) {
protected String genTypeNameMethodParam(TypeInfo type) {
if (isAsyncFunctionType(type)) {
ParameterizedTypeInfo pt = (ParameterizedTypeInfo) type;
return "java.util.function.Function<" + genTypeName(pt.getArg(0)) + ", Single<" + genTypeName(((ParameterizedTypeInfo)pt.getArg(1)).getArg(0)) + ">>";
} else if (isAsyncSupplierType(type)) {
ParameterizedTypeInfo pt = (ParameterizedTypeInfo) type;
return "java.util.function.Supplier<Single<" + genTypeName(((ParameterizedTypeInfo)pt.getArg(0)).getArg(0)) + ">>";
} else {
return genTypeName(type);
}
}

protected String genTypeName(TypeInfo type) {
if (type.isParameterized()) {
ParameterizedTypeInfo pt = (ParameterizedTypeInfo) type;
return genTypeName(pt.getRaw()) + pt.getArgs().stream().map(this::genTypeName).collect(joining(", ", "<", ">"));
Expand Down Expand Up @@ -668,6 +683,20 @@ private String genInvokeDelegate(ClassModel model, MethodInfo method) {
return ret.toString();
}

protected abstract String genConvertRxToFuture(TypeInfo type, String paramName);

private boolean isAsyncFunctionType(TypeInfo type) {
if (!type.isParameterized() || !type.getRaw().getName().equals(Function.class.getCanonicalName())) return false;
TypeInfo returnType = ((ParameterizedTypeInfo)type).getArg(1);
return returnType.getRaw() != null && returnType.getRaw().getName().equals("io.vertx.core.Future");
}

private boolean isAsyncSupplierType(TypeInfo type) {
if (!type.isParameterized() || !type.getRaw().getName().equals(Handler.class.getCanonicalName())) return false;
TypeInfo returnType = ((ParameterizedTypeInfo)type).getArg(0);
return returnType.getRaw() != null && returnType.getRaw().getName().equals("io.vertx.core.Future");
}

private boolean isSameType(TypeInfo type, MethodInfo method) {
ClassKind kind = type.getKind();
if (kind.basic || kind.json || kind == DATA_OBJECT || kind == ENUM || kind == OTHER || kind == THROWABLE || kind == VOID) {
Expand All @@ -693,6 +722,10 @@ private boolean isSameType(TypeInfo type, MethodInfo method) {
return false;
}

protected String getRxFutureType() {
return "Single";
}

private String genConvParam(TypeInfo type, MethodInfo method, String expr) {
ClassKind kind = type.getKind();
if (isSameType(type, method)) {
Expand All @@ -714,7 +747,16 @@ private String genConvParam(TypeInfo type, MethodInfo method, String expr) {
if (kind == HANDLER) {
TypeInfo eventType = parameterizedTypeInfo.getArg(0);
ClassKind eventKind = eventType.getKind();
if (eventKind == ASYNC_RESULT) {
if (isAsyncSupplierType(type)) {
TypeInfo resultType = ((ParameterizedTypeInfo) eventType).getArg(0);
String retTypeConversion = genConvParam(resultType, method, "r");
String finalMapping = retTypeConversion.equals("r") ? "" : ".map(r -> " + retTypeConversion + ")";
return "new Handler<io.vertx.core.Future<" + resultType.getName() + ">>() {\n" +
" public void handle(io.vertx.core.Future<" + resultType.getName() + "> fut) {\n" +
" " + expr + ".get()" + finalMapping + ".subscribe(fut::complete, fut::fail);\n" +
" }\n" +
" }";
} else if (eventKind == ASYNC_RESULT) {
TypeInfo resultType = ((ParameterizedTypeInfo) eventType).getArg(0);
return "new Handler<AsyncResult<" + resultType.getName() + ">>() {\n" +
" public void handle(AsyncResult<" + resultType.getName() + "> ar) {\n" +
Expand All @@ -733,14 +775,27 @@ private String genConvParam(TypeInfo type, MethodInfo method, String expr) {
" }";
}
} else if (kind == FUNCTION) {
TypeInfo argType = parameterizedTypeInfo.getArg(0);
TypeInfo retType = parameterizedTypeInfo.getArg(1);
return "new java.util.function.Function<" + argType.getName() + "," + retType.getName() + ">() {\n" +
" public " + retType.getName() + " apply(" + argType.getName() + " arg) {\n" +
" " + genTypeName(retType) + " ret = " + expr + ".apply(" + genConvReturn(argType, method, "arg") + ");\n" +
" return " + genConvParam(retType, method, "ret") + ";\n" +
" }\n" +
" }";
if (isAsyncFunctionType(type)) {
TypeInfo argType = parameterizedTypeInfo.getArg(0);
TypeInfo asyncRetType = ((ParameterizedTypeInfo)parameterizedTypeInfo.getArg(1)).getArg(0);
String retTypeConversion = genConvParam(asyncRetType, method, "r");
String finalMapping = retTypeConversion.equals("r") ? "" : ".map(r -> " + retTypeConversion + ")";
return "new java.util.function.Function<" + argType.getName() + ",io.vertx.core.Future<" + asyncRetType.getName() + ">>() {\n" +
" public io.vertx.core.Future<" + asyncRetType.getName() + "> apply(" + argType.getName() + " arg) {\n" +
" " + getRxFutureType() + "<" + genTypeName(asyncRetType) + "> ret = " + expr + ".apply(" + genConvReturn(argType, method, "arg") + ");\n" +
" return " + genConvertRxToFuture(asyncRetType, "ret") + finalMapping + ";\n" +
" }\n" +
" }";
} else {
TypeInfo argType = parameterizedTypeInfo.getArg(0);
TypeInfo retType = parameterizedTypeInfo.getArg(1);
return "new java.util.function.Function<" + argType.getName() + "," + retType.getName() + ">() {\n" +
" public " + retType.getName() + " apply(" + argType.getName() + " arg) {\n" +
" " + genTypeName(retType) + " ret = " + expr + ".apply(" + genConvReturn(argType, method, "arg") + ");\n" +
" return " + genConvParam(retType, method, "ret") + ";\n" +
" }\n" +
" }";
}
} else if (kind == LIST || kind == SET) {
return expr + ".stream().map(elt -> " + genConvParam(parameterizedTypeInfo.getArg(0), method, "elt") + ").collect(java.util.stream.Collectors.to" + type.getRaw().getSimpleName() + "())";
} else if (kind == MAP) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ protected void genRxImports(ClassModel model, PrintWriter writer) {
super.genRxImports(model, writer);
}

@Override
protected String genConvertRxToFuture(TypeInfo type, String paramName) {
return "io.vertx.rx.java.RxHelper.toFuture(" + paramName + ")";
}

@Override
protected void genToObservable(TypeInfo streamType, PrintWriter writer) {
writer.print(" private rx.Observable<");
Expand Down
11 changes: 7 additions & 4 deletions rx-java-gen/src/main/java/io/vertx/rx/java/RxHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import io.vertx.core.streams.ReadStream;
import io.vertx.core.streams.WriteStream;
import io.vertx.rx.java.impl.WriteStreamSubscriberImpl;
import rx.Observable;
import rx.Observer;
import rx.Scheduler;
import rx.Subscriber;
import rx.*;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.plugins.RxJavaSchedulersHook;
Expand Down Expand Up @@ -175,6 +172,12 @@ public static <T> Handler<AsyncResult<T>> toFuture(Observer<T> observer) {
return observable.toHandler();
}

public static <T> Future<T> toFuture(Single<T> single) {
Future<T> fut = Future.future();
single.subscribe(fut::complete, fut::fail);
return fut;
}

/**
* Adapt a {@link Subscriber} as a {@code Handler<T>;}.<p/>
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.vertx.codegen.rxjava;

import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;

import java.util.function.Function;

@VertxGen
public interface MethodWithAsyncFunction {

void method(Function<String, Future<String>> fn, Handler<AsyncResult<String>> resultHandler);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.vertx.codegen.rxjava;

import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;

@VertxGen
public interface MethodWithAsyncSupplier {

void method(Handler<Future<String>> fn, Handler<AsyncResult<String>> resultHandler);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @author <a href="mailto:[email protected]">Julien Viet</a>
*/
@ModuleGen(name = "rxjava", groupPackage = "io.vertx")
package io.vertx.codegen.rxjava;

import io.vertx.codegen.annotations.ModuleGen;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.vertx.codegen.testmodel;

import io.vertx.codegen.annotations.Nullable;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.Future;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
* @author <a href="slinkydeveloper.com">Francesco Guardiani</a>
*/
@VertxGen
public interface AsyncFunctionParamTCK {

List<String> methodWithBasicParam(
Function<Byte, Future<String>> byteFunc,
Function<Short, Future<String>> shortFunc,
Function<Integer, Future<String>> integerFunc,
Function<Long, Future<String>> longFunc,
Function<Float, Future<String>> floatFunc,
Function<Double, Future<String>> doubleFunc,
Function<Boolean, Future<String>> booleanFunc,
Function<Character, Future<String>> charFunc,
Function<String, Future<String>> stringFunc
);

List<String> methodWithJsonParam(Function<JsonObject, Future<String>> objectFunc, Function<JsonArray, Future<String>> arrayFunc);

String methodWithVoidParam(Function<Void, Future<String>> func);
String methodWithUserTypeParam(RefedInterface1 arg, Function<RefedInterface1, Future<String>> func);
String methodWithObjectParam(Object arg, Function<Object, Future<String>> func);
String methodWithDataObjectParam(Function<TestDataObject, Future<String>> func);
String methodWithEnumParam(Function<TestEnum, Future<String>> func);
String methodWithListParam(Function<List<String>, Future<String>> stringFunc);
String methodWithSetParam(Function<Set<String>, Future<String>> func);
String methodWithMapParam(Function<Map<String, String>, Future<String>> func);

<T> String methodWithGenericParam(T t, Function<T, Future<String>> func);
<T> String methodWithGenericUserTypeParam(T t, Function<GenericRefedInterface<T>, Future<String>> func);

String methodWithBasicReturn(
Function<String, Future<Byte>> byteFunc,
Function<String, Future<Short>> shortFunc,
Function<String, Future<Integer>> integerFunc,
Function<String, Future<Long>> longFunc,
Function<String, Future<Float>> floatFunc,
Function<String, Future<Double>> doubleFunc,
Function<String, Future<Boolean>> booleanFunc,
Function<String, Future<Character>> charFunc,
Function<String, Future<String>> stringFunc
);

String methodWithJsonReturn(Function<String, Future<JsonObject>> objectFunc, Function<String, Future<JsonArray>> arrayFunc);
String methodWithDataObjectReturn(Function<String, Future<TestDataObject>> func);
String methodWithEnumReturn(Function<String, Future<TestEnum>> func);
String methodWithListReturn(Function<String, Future<List<String>>> func);
String methodWithSetReturn(Function<String, Future<Set<String>>> func);
String methodWithMapReturn(Function<String, Future<Map<String, String>>> func);
<T> String methodWithGenericReturn(Function<Integer, Future<T>> func);
<T> String methodWithGenericUserTypeReturn(Function<GenericRefedInterface<T>, Future<GenericRefedInterface<T>>> func);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.vertx.codegen.testmodel;

import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
* @author <a href="slinkydeveloper.com">Francesco Guardiani</a>
*/
@VertxGen
public interface AsyncSupplierParamTCK {

List<String> methodWithBasicParam(
Handler<Future<String>> byteFunc,
Handler<Future<String>> shortFunc,
Handler<Future<String>> integerFunc,
Handler<Future<String>> longFunc,
Handler<Future<String>> floatFunc,
Handler<Future<String>> doubleFunc,
Handler<Future<String>> booleanFunc,
Handler<Future<String>> charFunc,
Handler<Future<String>> stringFunc
);

List<String> methodWithJsonParam(Handler<Future<String>> objectFunc, Handler<Future<String>> arrayFunc);

String methodWithVoidParam(Handler<Future<String>> func);
String methodWithUserTypeParam(RefedInterface1 arg, Handler<Future<String>> func);
String methodWithObjectParam(Object arg, Handler<Future<String>> func);
String methodWithDataObjectParam(Handler<Future<String>> func);
String methodWithEnumParam(Handler<Future<String>> func);
String methodWithListParam(Handler<Future<String>> stringFunc);
String methodWithSetParam(Handler<Future<String>> func);
String methodWithMapParam(Handler<Future<Map<String, String>>> func);

<T> String methodWithGenericParam(T t, Handler<Future<String>> func);
<T> String methodWithGenericUserTypeParam(T t, Handler<Future<String>> func);

String methodWithBasicReturn(
Handler<Future<Byte>> byteFunc,
Handler<Future<Short>> shortFunc,
Handler<Future<Integer>> integerFunc,
Handler<Future<Long>> longFunc,
Handler<Future<Float>> floatFunc,
Handler<Future<Double>> doubleFunc,
Handler<Future<Boolean>> booleanFunc,
Handler<Future<Character>> charFunc,
Handler<Future<String>> stringFunc
);

String methodWithJsonReturn(Handler<Future<JsonObject>> objectFunc, Handler<Future<JsonArray>> arrayFunc);
String methodWithDataObjectReturn(Handler<Future<TestDataObject>> func);
String methodWithEnumReturn(Handler<Future<TestEnum>> func);
String methodWithListReturn(Handler<Future<List<String>>> func);
String methodWithSetReturn(Handler<Future<Set<String>>> func);
String methodWithMapReturn(Handler<Future<Map<String, String>>> func);
<T> String methodWithGenericReturn(Handler<Future<T>> func);
<T> String methodWithGenericUserTypeReturn(Handler<Future<GenericRefedInterface<T>>> func);

}
Loading