Browse Source

Polish ReactiveAdapterRegistry

Issue: SPR-14902
pull/1248/head
Rossen Stoyanchev 8 years ago
parent
commit
e563326357
  1. 159
      spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java
  2. 17
      spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java

159
spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java

@ -67,99 +67,81 @@ public class ReactiveAdapterRegistry {
// Flux and Mono ahead of Publisher... // Flux and Mono ahead of Publisher...
registerMonoAdapter(Mono.class, registerReactiveType(
source -> (Mono<?>) source, source -> source, ReactiveTypeDescriptor.singleOptionalValue(Mono.class),
ReactiveTypeDescriptor.singleOptionalValue(Mono.class)); source -> (Mono<?>) source,
source -> source
);
registerFluxAdapter(Flux.class, registerReactiveType(ReactiveTypeDescriptor.multiValue(Flux.class),
source -> (Flux<?>) source, source -> source); source -> (Flux<?>) source,
source -> source);
registerFluxAdapter(Publisher.class, registerReactiveType(ReactiveTypeDescriptor.multiValue(Publisher.class),
source -> Flux.from((Publisher<?>) source), source -> source); source -> Flux.from((Publisher<?>) source),
source -> source);
registerMonoAdapter(CompletableFuture.class, registerReactiveType(
source -> Mono.fromFuture((CompletableFuture<?>) source), Mono::toFuture, ReactiveTypeDescriptor.singleOptionalValue(CompletableFuture.class),
ReactiveTypeDescriptor.singleOptionalValue(CompletableFuture.class) source -> Mono.fromFuture((CompletableFuture<?>) source),
source -> Mono.from(source).toFuture()
); );
if (rxJava1Present && rxJava1Adapter) { if (rxJava1Present && rxJava1Adapter) {
new RxJava1AdapterRegistrar().register(this); new RxJava1Registrar().registerAdapters(this);
} }
if (rxJava2Present) { if (rxJava2Present) {
new RxJava2AdapterRegistrar().register(this); new RxJava2Registrar().registerAdapters(this);
} }
} }
/** /**
* Register an adapter for adapting to and from a {@link Mono}. * Register a reactive type along with functions to adapt to and from a
* <p>The provided functions can assume that input will never be {@code null} * Reactive Streams {@link Publisher}. The functions can assume their
* and also that any {@link Optional} wrapper is unwrapped. * input is never be {@code null} nor {@link Optional}.
*/ */
public void registerMonoAdapter(Class<?> reactiveType, Function<Object, Mono<?>> toAdapter, public void registerReactiveType(ReactiveTypeDescriptor descriptor,
Function<Mono<?>, Object> fromAdapter, ReactiveTypeDescriptor descriptor) { Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
this.adapters.add(new MonoReactiveAdapter(toAdapter, fromAdapter, descriptor)); ReactiveAdapter adapter = (descriptor.isMultiValue() ?
} new FluxReactiveAdapter(toAdapter, fromAdapter, descriptor) :
new MonoReactiveAdapter(toAdapter, fromAdapter, descriptor));
/** this.adapters.add(adapter);
* Register an adapter for adapting to and from a {@link Flux}.
* <p>The provided functions can assume that input will never be {@code null}
* and also that any {@link Optional} wrapper is unwrapped.
*/
public void registerFluxAdapter(Class<?> reactiveType, Function<Object, Flux<?>> toAdapter,
Function<Flux<?>, Object> fromAdapter) {
this.adapters.add(new FluxReactiveAdapter(toAdapter, fromAdapter,
ReactiveTypeDescriptor.multiValue(reactiveType)));
} }
/** /**
* Get the adapter for the given reactive type to adapt from. * Get the adapter to use to adapt from the given reactive type.
*/ */
public ReactiveAdapter getAdapterFrom(Class<?> reactiveType) { public ReactiveAdapter getAdapterFrom(Class<?> reactiveType) {
return getAdapterFrom(reactiveType, null); return getAdapterFrom(reactiveType, null);
} }
/** /**
* Get the adapter for the given reactive type to adapt from. * Get the adapter to use to adapt from the given reactive type. Or if the
* If the instance is not {@code null} its actual type is used to check. * "source" object is not {@code null} its actual type is used instead.
*/ */
public ReactiveAdapter getAdapterFrom(Class<?> reactiveType, Object adaptee) { public ReactiveAdapter getAdapterFrom(Class<?> reactiveType, Object source) {
Class<?> actualType = getActualType(reactiveType, adaptee); source = unwrapOptional(source);
return getAdapterInternal(supportedType -> supportedType.isAssignableFrom(actualType)); Class<?> clazz = (source != null ? source.getClass() : reactiveType);
return getAdapter(type -> type.isAssignableFrom(clazz));
} }
/** /**
* Get the adapter for the given reactive type to adapt to. * Get the adapter for the given reactive type to adapt to.
*/ */
public ReactiveAdapter getAdapterTo(Class<?> reactiveType) { public ReactiveAdapter getAdapterTo(Class<?> reactiveType) {
return getAdapterTo(reactiveType, null); return getAdapter(reactiveType::equals);
}
/**
* Get the adapter for the given reactive type to adapt to.
* If the instance is not {@code null} its actual type is used to check.
*/
public ReactiveAdapter getAdapterTo(Class<?> reactiveType, Object adaptee) {
Class<?> actualType = getActualType(reactiveType, adaptee);
return getAdapterInternal(supportedType -> supportedType.equals(actualType));
} }
private ReactiveAdapter getAdapterInternal(Predicate<Class<?>> predicate) { private ReactiveAdapter getAdapter(Predicate<Class<?>> predicate) {
return this.adapters.stream() return this.adapters.stream()
.filter(adapter -> predicate.test(adapter.getDescriptor().getReactiveType())) .filter(adapter -> predicate.test(adapter.getDescriptor().getReactiveType()))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
private static Class<?> getActualType(Class<?> reactiveType, Object adaptee) {
adaptee = unwrapOptional(adaptee);
return (adaptee != null ? adaptee.getClass() : reactiveType);
}
private static Object unwrapOptional(Object value) { private static Object unwrapOptional(Object value) {
return (value instanceof Optional ? ((Optional<?>) value).orElse(null) : value); return (value instanceof Optional ? ((Optional<?>) value).orElse(null) : value);
} }
@ -168,14 +150,14 @@ public class ReactiveAdapterRegistry {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static class MonoReactiveAdapter implements ReactiveAdapter { private static class MonoReactiveAdapter implements ReactiveAdapter {
private final Function<Object, Mono<?>> toAdapter; private final Function<Object, Publisher<?>> toAdapter;
private final Function<Mono<?>, Object> fromAdapter; private final Function<Publisher<?>, Object> fromAdapter;
private final ReactiveTypeDescriptor descriptor; private final ReactiveTypeDescriptor descriptor;
MonoReactiveAdapter(Function<Object, Mono<?>> to, Function<Mono<?>, Object> from, MonoReactiveAdapter(Function<Object, Publisher<?>> to, Function<Publisher<?>, Object> from,
ReactiveTypeDescriptor descriptor) { ReactiveTypeDescriptor descriptor) {
this.toAdapter = to; this.toAdapter = to;
@ -194,7 +176,7 @@ public class ReactiveAdapterRegistry {
if (source == null) { if (source == null) {
return Mono.empty(); return Mono.empty();
} }
return (Mono<T>) this.toAdapter.apply(source); return (Mono<T>) Mono.from(this.toAdapter.apply(source));
} }
@Override @Override
@ -203,7 +185,7 @@ public class ReactiveAdapterRegistry {
if (source == null) { if (source == null) {
return Flux.empty(); return Flux.empty();
} }
return (Flux<T>) this.toMono(source).flux(); return (Flux<T>) toMono(source).flux();
} }
@Override @Override
@ -213,21 +195,21 @@ public class ReactiveAdapterRegistry {
@Override @Override
public Object fromPublisher(Publisher<?> source) { public Object fromPublisher(Publisher<?> source) {
return (source != null ? this.fromAdapter.apply((Mono<?>) source) : null); return (source != null ? this.fromAdapter.apply(source) : null);
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static class FluxReactiveAdapter implements ReactiveAdapter { private static class FluxReactiveAdapter implements ReactiveAdapter {
private final Function<Object, Flux<?>> toAdapter; private final Function<Object, Publisher<?>> toAdapter;
private final Function<Flux<?>, Object> fromAdapter; private final Function<Publisher<?>, Object> fromAdapter;
private final ReactiveTypeDescriptor descriptor; private final ReactiveTypeDescriptor descriptor;
FluxReactiveAdapter(Function<Object, Flux<?>> to, Function<Flux<?>, Object> from, FluxReactiveAdapter(Function<Object, Publisher<?>> to, Function<Publisher<?>, Object> from,
ReactiveTypeDescriptor descriptor) { ReactiveTypeDescriptor descriptor) {
this.descriptor = descriptor; this.descriptor = descriptor;
@ -246,7 +228,7 @@ public class ReactiveAdapterRegistry {
if (source == null) { if (source == null) {
return Mono.empty(); return Mono.empty();
} }
return (Mono<T>) this.toAdapter.apply(source).next(); return (Mono<T>) toFlux(source).next();
} }
@Override @Override
@ -255,7 +237,7 @@ public class ReactiveAdapterRegistry {
if (source == null) { if (source == null) {
return Flux.empty(); return Flux.empty();
} }
return (Flux<T>) this.toAdapter.apply(source); return (Flux<T>) Flux.from(this.toAdapter.apply(source));
} }
@Override @Override
@ -265,56 +247,59 @@ public class ReactiveAdapterRegistry {
@Override @Override
public Object fromPublisher(Publisher<?> source) { public Object fromPublisher(Publisher<?> source) {
return (source != null ? this.fromAdapter.apply((Flux<?>) source) : null); return (source != null ? this.fromAdapter.apply(source) : null);
} }
} }
private static class RxJava1AdapterRegistrar { private static class RxJava1Registrar {
public void register(ReactiveAdapterRegistry registry) { public void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerFluxAdapter(rx.Observable.class, registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(rx.Observable.class),
source -> Flux.from(RxReactiveStreams.toPublisher((rx.Observable<?>) source)), source -> Flux.from(RxReactiveStreams.toPublisher((rx.Observable<?>) source)),
RxReactiveStreams::toObservable RxReactiveStreams::toObservable
); );
registry.registerMonoAdapter(rx.Single.class, registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class),
source -> Mono.from(RxReactiveStreams.toPublisher((rx.Single<?>) source)), source -> Mono.from(RxReactiveStreams.toPublisher((rx.Single<?>) source)),
RxReactiveStreams::toSingle, RxReactiveStreams::toSingle
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class)
); );
registry.registerMonoAdapter(rx.Completable.class, registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(rx.Completable.class),
source -> Mono.from(RxReactiveStreams.toPublisher((rx.Completable) source)), source -> Mono.from(RxReactiveStreams.toPublisher((rx.Completable) source)),
RxReactiveStreams::toCompletable, RxReactiveStreams::toCompletable
ReactiveTypeDescriptor.noValue(rx.Completable.class)
); );
} }
} }
private static class RxJava2AdapterRegistrar { private static class RxJava2Registrar {
public void register(ReactiveAdapterRegistry registry) { public void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerFluxAdapter(Flowable.class, registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(Flowable.class),
source -> Flux.from((Flowable<?>) source), source -> Flux.from((Flowable<?>) source),
source-> Flowable.fromPublisher(source) source-> Flowable.fromPublisher(source)
); );
registry.registerFluxAdapter(io.reactivex.Observable.class, registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class),
source -> Flux.from(((io.reactivex.Observable<?>) source).toFlowable(BackpressureStrategy.BUFFER)), source -> Flux.from(((io.reactivex.Observable<?>) source).toFlowable(BackpressureStrategy.BUFFER)),
source -> Flowable.fromPublisher(source).toObservable() source -> Flowable.fromPublisher(source).toObservable()
); );
registry.registerMonoAdapter(io.reactivex.Single.class, registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
source -> Mono.from(((io.reactivex.Single<?>) source).toFlowable()), source -> Mono.from(((io.reactivex.Single<?>) source).toFlowable()),
source -> Flowable.fromPublisher(source).toObservable().singleElement().toSingle(), source -> Flowable.fromPublisher(source).toObservable().singleElement().toSingle()
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class)
); );
registry.registerMonoAdapter(Maybe.class, registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(Maybe.class),
source -> Mono.from(((Maybe<?>) source).toFlowable()), source -> Mono.from(((Maybe<?>) source).toFlowable()),
source -> Flowable.fromPublisher(source).toObservable().singleElement(), source -> Flowable.fromPublisher(source).toObservable().singleElement()
ReactiveTypeDescriptor.singleOptionalValue(Maybe.class)
); );
registry.registerMonoAdapter(io.reactivex.Completable.class, registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class),
source -> Mono.from(((io.reactivex.Completable) source).toFlowable()), source -> Mono.from(((io.reactivex.Completable) source).toFlowable()),
source -> Flowable.fromPublisher(source).toObservable().ignoreElements(), source -> Flowable.fromPublisher(source).toObservable().ignoreElements()
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class)
); );
} }
} }

17
spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java

@ -85,6 +85,23 @@ public class ReactiveTypeDescriptor {
} }
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
return this.reactiveType.equals(((ReactiveTypeDescriptor) other).reactiveType);
}
@Override
public int hashCode() {
return this.reactiveType.hashCode();
}
/** /**
* Descriptor for a reactive type that can produce 0..N values. * Descriptor for a reactive type that can produce 0..N values.
*/ */

Loading…
Cancel
Save