Use Void as input type for Supplier, etc.

This commit is contained in:
Dave Syer
2018-02-26 13:48:36 +00:00
parent f9e4546070
commit 5203401e00
5 changed files with 62 additions and 15 deletions

View File

@@ -18,7 +18,9 @@ package org.springframework.cloud.function.context;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
@@ -219,6 +221,9 @@ public class FunctionType {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
if (parameterizedType.getActualTypeArguments().length == 1) {
if (isVoid(parameterizedType, paramType)) {
return Void.class;
}
// There's only one
index = 0;
}
@@ -245,6 +250,17 @@ public class FunctionType {
return param;
}
private boolean isVoid(ParameterizedType parameterizedType, ParamType paramType) {
Class<?> rawType = extractClass(parameterizedType.getRawType(), paramType);
if (Consumer.class.isAssignableFrom(rawType) && paramType.isOutput()) {
return true;
}
if (Supplier.class.isAssignableFrom(rawType) && paramType.isInput()) {
return true;
}
return false;
}
private Type extractNestedType(ParamType paramType, Type param) {
if (!paramType.isInnerWrapper() && param instanceof ParameterizedType) {
if (((ParameterizedType) param).getRawType().getTypeName()

View File

@@ -18,7 +18,9 @@ package org.springframework.cloud.function.context;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.Test;
@@ -99,6 +101,30 @@ public class FunctionTypeTests {
assertThat(function.isMessage()).isEqualTo(false);
}
@Test
public void pojoConsumerFromType() {
Type type = ResolvableType.forClassWithGenerics(Consumer.class, Foo.class)
.getType();
FunctionType function = new FunctionType(type);
assertThat(function.getInputType()).isEqualTo(Foo.class);
assertThat(function.getOutputType()).isEqualTo(Void.class);
assertThat(function.getInputWrapper()).isEqualTo(Foo.class);
assertThat(function.getOutputWrapper()).isEqualTo(Void.class);
assertThat(function.isMessage()).isEqualTo(false);
}
@Test
public void pojoSupplierFromType() {
Type type = ResolvableType.forClassWithGenerics(Supplier.class, Foo.class)
.getType();
FunctionType function = new FunctionType(type);
assertThat(function.getInputType()).isEqualTo(Void.class);
assertThat(function.getOutputType()).isEqualTo(Foo.class);
assertThat(function.getInputWrapper()).isEqualTo(Void.class);
assertThat(function.getOutputWrapper()).isEqualTo(Foo.class);
assertThat(function.isMessage()).isEqualTo(false);
}
@Test
public void plainFunctionFromApi() {
FunctionType function = FunctionType.from(Integer.class).to(String.class);

View File

@@ -136,9 +136,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
assertThat(catalog.lookupFunction("names,foos")).isNull();
assertThat(inspector.getOutputType(catalog.lookupSupplier("names,foos")))
.isAssignableFrom(Foo.class);
// The input type is the same as the output type of the first element in the chain
// The input type is the same as the input type of the first element in the chain
assertThat(inspector.getInputType(catalog.lookupSupplier("names,foos")))
.isAssignableFrom(String.class);
.isAssignableFrom(Void.class);
}
@Test
@@ -148,9 +148,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
assertThat(catalog.lookupFunction("foos,print")).isNull();
assertThat(inspector.getInputType(catalog.lookupConsumer("foos,print")))
.isAssignableFrom(String.class);
// The output type is the same as the input type of the last element in the chain
// The output type is the same as the output type of the last element in the chain
assertThat(inspector.getOutputType(catalog.lookupConsumer("foos,print")))
.isAssignableFrom(Foo.class);
.isAssignableFrom(Void.class);
}
@Test
@@ -543,7 +543,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
@EnableAutoConfiguration
@Configuration
protected static class SingletonMessageConfiguration implements BeanFactoryPostProcessor {
protected static class SingletonMessageConfiguration
implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
@@ -570,7 +571,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
}
protected static class SingletonMessageFunction implements Function<Message<Integer>, Message<String>> {
protected static class SingletonMessageFunction
implements Function<Message<Integer>, Message<String>> {
@Override
public Message<String> apply(Message<Integer> input) {
@@ -672,24 +674,28 @@ public class ContextFunctionCatalogAutoConfigurationTests {
@EnableAutoConfiguration
@Configuration
protected static class FactoryBeanConfiguration implements BeanDefinitionRegistryPostProcessor {
protected static class FactoryBeanConfiguration
implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition beanDefinition = new RootBeanDefinition(FunctionFactoryBean.class);
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
FunctionFactoryBean.class);
beanDefinition.setSource(new DescriptiveResource("Function"));
registry.registerBeanDefinition("function", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
}
private static class FunctionFactoryBean extends AbstractFactoryBean<Function<String, String>> {
private static class FunctionFactoryBean
extends AbstractFactoryBean<Function<String, String>> {
@Override
public Class<?> getObjectType() {