General polishing
- minor refactoring of FunctionRegistration and some javadoc - general cleanup of ContextFunctionCatalogAutoConfiguration (mainly consolidated repeatable code) Fixes gh-98
This commit is contained in:
committed by
Dave Syer
parent
20561ea987
commit
592eef9d52
@@ -72,6 +72,7 @@ import reactor.core.publisher.Flux;
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(InMemoryFunctionCatalog.class)
|
||||
@@ -116,22 +117,22 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public Class<?> getInputWrapper(Object function) {
|
||||
return processor.findInputWrapper(function);
|
||||
return processor.findType(function, ParamType.INPUT_WRAPPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getOutputWrapper(Object function) {
|
||||
return processor.findOutputWrapper(function);
|
||||
return processor.findType(function, ParamType.OUTPUT_WRAPPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getInputType(Object function) {
|
||||
return processor.findInputType(function);
|
||||
return processor.findType(function, ParamType.INPUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getOutputType(Object function) {
|
||||
return processor.findOutputType(function);
|
||||
return processor.findType(function, ParamType.OUTPUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,23 +164,19 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
private Object convert(Object function, String value) {
|
||||
if (conversionService == null) {
|
||||
if (registry instanceof ConfigurableListableBeanFactory) {
|
||||
ConversionService conversionService = ((ConfigurableBeanFactory) this.registry)
|
||||
.getConversionService();
|
||||
if (conversionService != null) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
else {
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
|
||||
for (String name : factory.getBeanDefinitionNames()) {
|
||||
if (isGeneric(factory, name, Supplier.class)) {
|
||||
this.suppliers.add(name);
|
||||
}
|
||||
else if (isGeneric(factory, name, Function.class)) {
|
||||
this.functions.add(name);
|
||||
}
|
||||
else if (isGeneric(factory, name, Consumer.class)) {
|
||||
this.consumers.add(name);
|
||||
}
|
||||
}
|
||||
Class<?> type = findInputType(function);
|
||||
return conversionService.canConvert(String.class, type)
|
||||
? conversionService.convert(value, type)
|
||||
: value;
|
||||
}
|
||||
|
||||
public Set<FunctionRegistration<?>> merge(
|
||||
@@ -200,8 +197,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
// Add consumers that were not already registered
|
||||
for (String key : consumers.keySet()) {
|
||||
if (!targets.containsKey(consumers.get(key))) {
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>()
|
||||
.target(consumers.get(key)).names(getAliases(key));
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>(consumers.get(key)).names(getAliases(key));
|
||||
targets.put(target.getTarget(), key);
|
||||
registrations.add(target);
|
||||
}
|
||||
@@ -209,8 +205,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
// Add suppliers that were not already registered
|
||||
for (String key : suppliers.keySet()) {
|
||||
if (!targets.containsKey(suppliers.get(key))) {
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>()
|
||||
.target(suppliers.get(key)).names(getAliases(key));
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>(suppliers.get(key)).names(getAliases(key));
|
||||
targets.put(target.getTarget(), key);
|
||||
registrations.add(target);
|
||||
}
|
||||
@@ -218,8 +213,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
// Add functions that were not already registered
|
||||
for (String key : functions.keySet()) {
|
||||
if (!targets.containsKey(functions.get(key))) {
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>()
|
||||
.target(functions.get(key)).names(getAliases(key));
|
||||
FunctionRegistration<Object> target = new FunctionRegistration<Object>(functions.get(key)).names(getAliases(key));
|
||||
targets.put(target.getTarget(), key);
|
||||
registrations.add(target);
|
||||
}
|
||||
@@ -234,16 +228,24 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
return registrations;
|
||||
}
|
||||
|
||||
private Object convert(Object function, String value) {
|
||||
if (conversionService == null && registry instanceof ConfigurableListableBeanFactory) {
|
||||
ConversionService conversionService = ((ConfigurableBeanFactory) this.registry).getConversionService();
|
||||
this.conversionService = conversionService != null ? conversionService : new DefaultConversionService();
|
||||
}
|
||||
Class<?> type = findType(function, ParamType.INPUT);
|
||||
return conversionService.canConvert(String.class, type)
|
||||
? conversionService.convert(value, type)
|
||||
: value;
|
||||
}
|
||||
|
||||
private Collection<String> getAliases(String key) {
|
||||
Collection<String> names = new LinkedHashSet<>();
|
||||
String value = getQualifier(key);
|
||||
if (value.equals(key)) {
|
||||
names.add(key);
|
||||
names.addAll(Arrays.asList(registry.getAliases(key)));
|
||||
}
|
||||
else {
|
||||
names.add(value);
|
||||
}
|
||||
names.add(value);
|
||||
return names;
|
||||
}
|
||||
|
||||
@@ -264,85 +266,33 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
private String getQualifier(String key) {
|
||||
if (!registry.containsBeanDefinition(key)) {
|
||||
return key;
|
||||
}
|
||||
String value = key;
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(key);
|
||||
Object source = beanDefinition.getSource();
|
||||
if (source instanceof StandardMethodMetadata) {
|
||||
StandardMethodMetadata metadata = (StandardMethodMetadata) source;
|
||||
Qualifier qualifier = AnnotatedElementUtils.findMergedAnnotation(
|
||||
metadata.getIntrospectedMethod(), Qualifier.class);
|
||||
if (qualifier != null && qualifier.value().length() > 0) {
|
||||
return qualifier.value();
|
||||
if (registry.containsBeanDefinition(key)) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(key);
|
||||
Object source = beanDefinition.getSource();
|
||||
if (source instanceof StandardMethodMetadata) {
|
||||
StandardMethodMetadata metadata = (StandardMethodMetadata) source;
|
||||
Qualifier qualifier = AnnotatedElementUtils.findMergedAnnotation(
|
||||
metadata.getIntrospectedMethod(), Qualifier.class);
|
||||
if (qualifier != null && qualifier.value().length() > 0) {
|
||||
return qualifier.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
return key;
|
||||
}
|
||||
|
||||
private Supplier<?> target(Supplier<?> target, String key) {
|
||||
if (this.suppliers.contains(key)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<?>> supplier = (Supplier<Flux<?>>) target;
|
||||
return supplier;
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private <T> T target(T target, String key) {
|
||||
if (target instanceof Supplier<?> && !isFluxSupplier(key, (Supplier<?>)target)) {
|
||||
target = (T) new FluxSupplier((Supplier<?>)target);
|
||||
}
|
||||
else if (!isFluxSupplier(key, target)) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
FluxSupplier value = new FluxSupplier(target);
|
||||
return value;
|
||||
else if (target instanceof Function<?, ?> && !isFluxFunction(key, (Function<?, ?>)target)) {
|
||||
target = (T) new FluxFunction((Function<?, ?>)target);
|
||||
}
|
||||
else {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
private Function<?, ?> target(Function<?, ?> target, String key) {
|
||||
if (this.functions.contains(key)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<?>, Flux<?>> function = (Function<Flux<?>, Flux<?>>) target;
|
||||
return function;
|
||||
}
|
||||
else if (!isFluxFunction(key, target)) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
FluxFunction value = new FluxFunction(target);
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<?> target(Consumer<?> target, String key) {
|
||||
if (this.consumers.contains(key)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Consumer<Flux<?>> consumer = (Consumer<Flux<?>>) target;
|
||||
return consumer;
|
||||
}
|
||||
else if (!isFluxConsumer(key, target)) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
FluxConsumer value = new FluxConsumer(target);
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
|
||||
throws BeansException {
|
||||
for (String name : factory.getBeanDefinitionNames()) {
|
||||
if (isGenericSupplier(factory, name)) {
|
||||
this.suppliers.add(name);
|
||||
}
|
||||
else if (isGenericFunction(factory, name)) {
|
||||
this.functions.add(name);
|
||||
}
|
||||
else if (isGenericConsumer(factory, name)) {
|
||||
this.consumers.add(name);
|
||||
}
|
||||
else if (target instanceof Consumer<?> && !isFluxConsumer(key, (Consumer<?>)target)) {
|
||||
target = (T) new FluxConsumer((Consumer<?>)target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private boolean isFluxFunction(String name, Function<?, ?> function) {
|
||||
@@ -361,41 +311,25 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
private boolean hasFluxTypes(Object function) {
|
||||
return FunctionInspector.isWrapper(findInputWrapper(function))
|
||||
|| FunctionInspector.isWrapper(findOutputWrapper(function));
|
||||
return FunctionInspector.isWrapper(findType(function, ParamType.INPUT_WRAPPER))
|
||||
|| FunctionInspector.isWrapper(findType(function, ParamType.OUTPUT_WRAPPER));
|
||||
}
|
||||
|
||||
private boolean isGenericSupplier(ConfigurableListableBeanFactory factory,
|
||||
String name) {
|
||||
return factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Supplier.class, Flux.class))
|
||||
&& !factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Supplier.class,
|
||||
ResolvableType.forClassWithGenerics(Flux.class,
|
||||
String.class)));
|
||||
}
|
||||
|
||||
private boolean isGenericFunction(ConfigurableListableBeanFactory factory,
|
||||
String name) {
|
||||
return factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Function.class, Flux.class,
|
||||
Flux.class))
|
||||
&& !factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Function.class,
|
||||
ResolvableType.forClassWithGenerics(Flux.class,
|
||||
String.class),
|
||||
ResolvableType.forClassWithGenerics(Flux.class,
|
||||
String.class)));
|
||||
}
|
||||
|
||||
private boolean isGenericConsumer(ConfigurableListableBeanFactory factory,
|
||||
String name) {
|
||||
return factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Consumer.class, Flux.class))
|
||||
&& !factory.isTypeMatch(name,
|
||||
ResolvableType.forClassWithGenerics(Consumer.class,
|
||||
ResolvableType.forClassWithGenerics(Flux.class,
|
||||
String.class)));
|
||||
private boolean isGeneric(ConfigurableListableBeanFactory factory, String name, Class<?> functionalInterface) {
|
||||
ResolvableType matchingType = null;
|
||||
ResolvableType[] nonMatchingTypes = null;
|
||||
if (functionalInterface.isAssignableFrom(Function.class)) {
|
||||
matchingType = ResolvableType.forClassWithGenerics(Function.class, Flux.class, Flux.class);
|
||||
nonMatchingTypes = new ResolvableType[]{ResolvableType.forClassWithGenerics(Flux.class, String.class), ResolvableType.forClassWithGenerics(Flux.class, String.class)};
|
||||
}
|
||||
else {
|
||||
nonMatchingTypes = new ResolvableType[]{ResolvableType.forClassWithGenerics(Flux.class, String.class)};
|
||||
if (functionalInterface.isAssignableFrom(Consumer.class)) {
|
||||
matchingType = ResolvableType.forClassWithGenerics(Consumer.class, Flux.class);
|
||||
}
|
||||
matchingType = ResolvableType.forClassWithGenerics(Supplier.class, Flux.class);
|
||||
}
|
||||
return factory.isTypeMatch(name, matchingType) && !factory.isTypeMatch(name, ResolvableType.forClassWithGenerics(functionalInterface, nonMatchingTypes));
|
||||
}
|
||||
|
||||
private Class<?> findType(String name, AbstractBeanDefinition definition,
|
||||
@@ -544,66 +478,34 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
ParamType.OUTPUT_INNER_WRAPPER));
|
||||
}
|
||||
|
||||
private Class<?> findInputWrapper(Object function) {
|
||||
private Class<?> findType(Object function, ParamType type) {
|
||||
String name = registrations.get(function);
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return Object.class;
|
||||
}
|
||||
return findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.INPUT_WRAPPER);
|
||||
return findType(name, (AbstractBeanDefinition) registry.getBeanDefinition(name), type);
|
||||
}
|
||||
}
|
||||
|
||||
static enum ParamType {
|
||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
||||
|
||||
public boolean isOutput() {
|
||||
return this == OUTPUT || this == OUTPUT_WRAPPER
|
||||
|| this == OUTPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
private Class<?> findOutputWrapper(Object function) {
|
||||
String name = registrations.get(function);
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return Object.class;
|
||||
}
|
||||
return findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.OUTPUT_WRAPPER);
|
||||
public boolean isInput() {
|
||||
return this == INPUT || this == INPUT_WRAPPER
|
||||
|| this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
private Class<?> findInputType(Object function) {
|
||||
String name = registrations.get(function);
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return Object.class;
|
||||
}
|
||||
return findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.INPUT);
|
||||
public boolean isWrapper() {
|
||||
return this == OUTPUT_WRAPPER || this == INPUT_WRAPPER;
|
||||
}
|
||||
|
||||
private Class<?> findOutputType(Object function) {
|
||||
String name = registrations.get(function);
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return Object.class;
|
||||
}
|
||||
return findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.OUTPUT);
|
||||
}
|
||||
|
||||
static enum ParamType {
|
||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
||||
|
||||
public boolean isOutput() {
|
||||
return this == OUTPUT || this == OUTPUT_WRAPPER
|
||||
|| this == OUTPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isInput() {
|
||||
return this == INPUT || this == INPUT_WRAPPER
|
||||
|| this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isWrapper() {
|
||||
return this == OUTPUT_WRAPPER || this == INPUT_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isInnerWrapper() {
|
||||
return this == OUTPUT_INNER_WRAPPER || this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
public boolean isInnerWrapper() {
|
||||
return this == OUTPUT_INNER_WRAPPER || this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,22 +23,22 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class FunctionRegistration<T> {
|
||||
class FunctionRegistration<T> {
|
||||
|
||||
private T target;
|
||||
|
||||
private Set<String> names = new LinkedHashSet<>();
|
||||
private final Set<String> names = new LinkedHashSet<>();
|
||||
|
||||
private Map<String, String> properties = new LinkedHashMap<>();
|
||||
private final Map<String, String> properties = new LinkedHashMap<>();
|
||||
|
||||
public FunctionRegistration() {
|
||||
}
|
||||
|
||||
public FunctionRegistration(T target) {
|
||||
FunctionRegistration(T target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,16 @@ public class FunctionRegistration<T> {
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will set the names for this registration clearing all
|
||||
* previous names first. If you want to add a name or set or
|
||||
* names to the existing set of names use {@link #names(Collection)}
|
||||
* or {@link #name(String)} or {@link #names(String...)} operations.
|
||||
* @param names
|
||||
*/
|
||||
public void setNames(Set<String> names) {
|
||||
this.names = names;
|
||||
this.names.clear();
|
||||
this.names.addAll(names);
|
||||
}
|
||||
|
||||
public T getTarget() {
|
||||
@@ -63,14 +71,21 @@ public class FunctionRegistration<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to override the target of this registration with a new target
|
||||
* that typically wraps the original target.
|
||||
* This typically happens when original target is wrapped into its {@link Flux}
|
||||
* counterpart (e.g., Function into FluxFunction)
|
||||
* @param target new target
|
||||
* @return this registration with new target
|
||||
*/
|
||||
public FunctionRegistration<T> target(T target) {
|
||||
this.target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FunctionRegistration<T> name(String name) {
|
||||
this.names.add(name);
|
||||
return this;
|
||||
return this.names(name);
|
||||
}
|
||||
|
||||
public FunctionRegistration<T> names(Collection<String> names) {
|
||||
@@ -79,8 +94,6 @@ public class FunctionRegistration<T> {
|
||||
}
|
||||
|
||||
public FunctionRegistration<T> names(String... names) {
|
||||
this.names.addAll(Arrays.asList(names));
|
||||
return this;
|
||||
return this.names(Arrays.asList(names));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user