29 changed files with 762 additions and 622 deletions
@ -0,0 +1,116 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2016 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.core; |
||||||
|
|
||||||
|
import org.reactivestreams.Publisher; |
||||||
|
import reactor.core.publisher.Flux; |
||||||
|
import reactor.core.publisher.Mono; |
||||||
|
|
||||||
|
/** |
||||||
|
* Contract for adapting to and from {@link Flux} and {@link Mono}. |
||||||
|
* |
||||||
|
* <p>An adapter supports a specific adaptee type whose stream semantics can be |
||||||
|
* checked via {@link #getDescriptor()}. |
||||||
|
* |
||||||
|
* <p>Use the {@link ReactiveAdapterRegistry} to obtain an adapter for a |
||||||
|
* supported adaptee type or to register additional adapters. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 5.0 |
||||||
|
*/ |
||||||
|
public interface ReactiveAdapter { |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a descriptor with further information about the adaptee. |
||||||
|
*/ |
||||||
|
Descriptor getDescriptor(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapt the given Object to a {@link Mono} |
||||||
|
* @param source the source object to adapt |
||||||
|
* @return the resulting {@link Mono} possibly empty |
||||||
|
*/ |
||||||
|
<T> Mono<T> toMono(Object source); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapt the given Object to a {@link Flux}. |
||||||
|
* @param source the source object to adapt |
||||||
|
* @return the resulting {@link Flux} possibly empty |
||||||
|
*/ |
||||||
|
<T> Flux<T> toFlux(Object source); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapt the given Object to a Publisher. |
||||||
|
* @param source the source object to adapt |
||||||
|
* @return the resulting {@link Mono} or {@link Flux} possibly empty |
||||||
|
*/ |
||||||
|
<T> Publisher<T> toPublisher(Object source); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapt the given Publisher to the target adaptee. |
||||||
|
* @param publisher the publisher to adapt |
||||||
|
* @return the resulting adaptee |
||||||
|
*/ |
||||||
|
Object fromPublisher(Publisher<?> publisher); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A descriptor with information about the adaptee stream semantics. |
||||||
|
*/ |
||||||
|
class Descriptor { |
||||||
|
|
||||||
|
private final boolean isMultiValue; |
||||||
|
|
||||||
|
private final boolean supportsEmpty; |
||||||
|
|
||||||
|
private final boolean isNoValue; |
||||||
|
|
||||||
|
|
||||||
|
public Descriptor(boolean isMultiValue, boolean canBeEmpty, boolean isNoValue) { |
||||||
|
this.isMultiValue = isMultiValue; |
||||||
|
this.supportsEmpty = canBeEmpty; |
||||||
|
this.isNoValue = isNoValue; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return {@code true} if the adaptee implies 0..N values can be produced |
||||||
|
* and is therefore a good fit to adapt to {@link Flux}. A {@code false} |
||||||
|
* return value implies the adaptee will produce 1 value at most and is |
||||||
|
* therefore a good fit for {@link Mono}. |
||||||
|
*/ |
||||||
|
public boolean isMultiValue() { |
||||||
|
return this.isMultiValue; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return {@code true} if the adaptee can complete without values. |
||||||
|
*/ |
||||||
|
public boolean supportsEmpty() { |
||||||
|
return this.supportsEmpty; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return {@code true} if the adaptee implies no values will be produced, |
||||||
|
* i.e. providing only completion or error signal. |
||||||
|
*/ |
||||||
|
public boolean isNoValue() { |
||||||
|
return this.isNoValue; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,282 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2016 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.core; |
||||||
|
|
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
import java.util.function.Function; |
||||||
|
import java.util.function.Predicate; |
||||||
|
|
||||||
|
import org.reactivestreams.Publisher; |
||||||
|
import reactor.adapter.RxJava1Adapter; |
||||||
|
import reactor.core.publisher.Flux; |
||||||
|
import reactor.core.publisher.Mono; |
||||||
|
import rx.Completable; |
||||||
|
import rx.Observable; |
||||||
|
import rx.Single; |
||||||
|
|
||||||
|
import org.springframework.core.ReactiveAdapter.Descriptor; |
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* A registry of adapters to adapt to {@link Flux} and {@link Mono}. |
||||||
|
* |
||||||
|
* <p>By default there are adapters for {@link CompletableFuture}, RxJava 1, and |
||||||
|
* also for a any Reactive Streams {@link Publisher}. Additional adapters can be |
||||||
|
* registered via {@link #registerFluxAdapter) and {@link #registerMonoAdapter}. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 5.0 |
||||||
|
*/ |
||||||
|
public class ReactiveAdapterRegistry { |
||||||
|
|
||||||
|
private static final boolean rxJava1Present = |
||||||
|
ClassUtils.isPresent("rx.Observable", ReactiveAdapterRegistry.class.getClassLoader()); |
||||||
|
|
||||||
|
|
||||||
|
private final Map<Class<?>, ReactiveAdapter> adapterMap = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a registry and auto-register default adapters. |
||||||
|
*/ |
||||||
|
public ReactiveAdapterRegistry() { |
||||||
|
|
||||||
|
// Flux and Mono ahead of Publisher...
|
||||||
|
registerMonoAdapter(Mono.class, |
||||||
|
source -> (Mono<?>) source, source -> source, new Descriptor(false, true, false)); |
||||||
|
|
||||||
|
registerFluxAdapter( |
||||||
|
Flux.class, source -> (Flux<?>) source, source -> source); |
||||||
|
|
||||||
|
registerFluxAdapter( |
||||||
|
Publisher.class, source -> Flux.from((Publisher<?>) source), source -> source); |
||||||
|
|
||||||
|
registerMonoAdapter(CompletableFuture.class, |
||||||
|
source -> Mono.fromFuture((CompletableFuture<?>) source), |
||||||
|
source -> Mono.from((Publisher<?>) source).toFuture(), |
||||||
|
new Descriptor(false, true, false) |
||||||
|
); |
||||||
|
|
||||||
|
if (rxJava1Present) { |
||||||
|
new RxJava1AdapterRegistrar().register(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Register an adapter for adapting to and from a {@link Mono}. The provided |
||||||
|
* functions can assume that input will never be {@code null} and also that |
||||||
|
* any {@link Optional} wrapper is unwrapped. |
||||||
|
*/ |
||||||
|
public void registerMonoAdapter(Class<?> adapteeType, |
||||||
|
Function<Object, Mono<?>> toAdapter, Function<Mono<?>, Object> fromAdapter, |
||||||
|
Descriptor descriptor) { |
||||||
|
|
||||||
|
this.adapterMap.put(adapteeType, new MonoReactiveAdapter(toAdapter, fromAdapter, descriptor)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Register an adapter for adapting to and from a {@link Flux}. 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<?> adapteeType, |
||||||
|
Function<Object, Flux<?>> toAdapter, Function<Flux<?>, Object> fromAdapter) { |
||||||
|
|
||||||
|
this.adapterMap.put(adapteeType, new FluxReactiveAdapter(toAdapter, fromAdapter)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get the adapter for the given adaptee type to adapt from. |
||||||
|
*/ |
||||||
|
public ReactiveAdapter getAdapterFrom(Class<?> adapteeType) { |
||||||
|
return getAdapterFrom(adapteeType, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the adapter for the given adaptee type to adapt from. |
||||||
|
* If the instance is not {@code null} its actual type is used to check. |
||||||
|
*/ |
||||||
|
public ReactiveAdapter getAdapterFrom(Class<?> adapteeType, Object adaptee) { |
||||||
|
Class<?> actualType = getActualType(adapteeType, adaptee); |
||||||
|
return getAdapterInternal(supportedType -> supportedType.isAssignableFrom(actualType)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the adapter for the given adaptee type to adapt to. |
||||||
|
*/ |
||||||
|
public ReactiveAdapter getAdapterTo(Class<?> adapteeType) { |
||||||
|
return getAdapterTo(adapteeType, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the adapter for the given adaptee type to adapt to. |
||||||
|
* If the instance is not {@code null} its actual type is used to check. |
||||||
|
*/ |
||||||
|
public ReactiveAdapter getAdapterTo(Class<?> adapteeType, Object adaptee) { |
||||||
|
Class<?> actualType = getActualType(adapteeType, adaptee); |
||||||
|
return getAdapterInternal(supportedType -> supportedType.equals(actualType)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static Class<?> getActualType(Class<?> adapteeType, Object adaptee) { |
||||||
|
adaptee = unwrapOptional(adaptee); |
||||||
|
return (adaptee != null ? adaptee.getClass() : adapteeType); |
||||||
|
} |
||||||
|
|
||||||
|
private static Object unwrapOptional(Object value) { |
||||||
|
if (value != null && value instanceof Optional) { |
||||||
|
value = ((Optional<?>) value).orElse(null); |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
private ReactiveAdapter getAdapterInternal(Predicate<Class<?>> adapteeTypePredicate) { |
||||||
|
return this.adapterMap.keySet().stream() |
||||||
|
.filter(adapteeTypePredicate) |
||||||
|
.map(this.adapterMap::get) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
private static class MonoReactiveAdapter implements ReactiveAdapter { |
||||||
|
|
||||||
|
private final Function<Object, Mono<?>> toAdapter; |
||||||
|
|
||||||
|
private final Function<Mono<?>, Object> fromAdapter; |
||||||
|
|
||||||
|
private final Descriptor descriptor; |
||||||
|
|
||||||
|
|
||||||
|
MonoReactiveAdapter(Function<Object, Mono<?>> to, Function<Mono<?>, Object> from, Descriptor descriptor) { |
||||||
|
this.toAdapter = to; |
||||||
|
this.fromAdapter = from; |
||||||
|
this.descriptor = descriptor; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Descriptor getDescriptor() { |
||||||
|
return this.descriptor; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Mono<T> toMono(Object source) { |
||||||
|
source = unwrapOptional(source); |
||||||
|
if (source == null) { |
||||||
|
return Mono.empty(); |
||||||
|
} |
||||||
|
return (Mono<T>) this.toAdapter.apply(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Flux<T> toFlux(Object source) { |
||||||
|
source = unwrapOptional(source); |
||||||
|
if (source == null) { |
||||||
|
return Flux.empty(); |
||||||
|
} |
||||||
|
return (Flux<T>) this.toMono(source).flux(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Publisher<T> toPublisher(Object source) { |
||||||
|
return toMono(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object fromPublisher(Publisher<?> source) { |
||||||
|
return (source != null ? this.fromAdapter.apply((Mono<?>) source) : null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
private static class FluxReactiveAdapter implements ReactiveAdapter { |
||||||
|
|
||||||
|
private final Function<Object, Flux<?>> toAdapter; |
||||||
|
|
||||||
|
private final Function<Flux<?>, Object> fromAdapter; |
||||||
|
|
||||||
|
private final Descriptor descriptor = new Descriptor(true, true, false); |
||||||
|
|
||||||
|
|
||||||
|
FluxReactiveAdapter(Function<Object, Flux<?>> to, Function<Flux<?>, Object> from) { |
||||||
|
this.toAdapter = to; |
||||||
|
this.fromAdapter = from; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Descriptor getDescriptor() { |
||||||
|
return this.descriptor; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Mono<T> toMono(Object source) { |
||||||
|
source = unwrapOptional(source); |
||||||
|
if (source == null) { |
||||||
|
return Mono.empty(); |
||||||
|
} |
||||||
|
return (Mono<T>) this.toAdapter.apply(source).next(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Flux<T> toFlux(Object source) { |
||||||
|
source = unwrapOptional(source); |
||||||
|
if (source == null) { |
||||||
|
return Flux.empty(); |
||||||
|
} |
||||||
|
return (Flux<T>) this.toAdapter.apply(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Publisher<T> toPublisher(Object source) { |
||||||
|
return toFlux(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object fromPublisher(Publisher<?> source) { |
||||||
|
return (source != null ? this.fromAdapter.apply((Flux<?>) source) : null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static class RxJava1AdapterRegistrar { |
||||||
|
|
||||||
|
public void register(ReactiveAdapterRegistry registry) { |
||||||
|
|
||||||
|
registry.registerFluxAdapter(Observable.class, |
||||||
|
source -> RxJava1Adapter.observableToFlux((Observable<?>) source), |
||||||
|
RxJava1Adapter::publisherToObservable |
||||||
|
); |
||||||
|
|
||||||
|
registry.registerMonoAdapter(Single.class, |
||||||
|
source -> RxJava1Adapter.singleToMono((Single<?>) source), |
||||||
|
RxJava1Adapter::publisherToSingle, |
||||||
|
new Descriptor(false, false, false) |
||||||
|
); |
||||||
|
|
||||||
|
registry.registerMonoAdapter(Completable.class, |
||||||
|
source -> RxJava1Adapter.completableToMono((Completable) source), |
||||||
|
RxJava1Adapter::publisherToCompletable, |
||||||
|
new Descriptor(false, true, true) |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,62 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.core.convert.support; |
|
||||||
|
|
||||||
import java.util.LinkedHashSet; |
|
||||||
import java.util.Set; |
|
||||||
import java.util.concurrent.CompletableFuture; |
|
||||||
|
|
||||||
import org.reactivestreams.Publisher; |
|
||||||
import reactor.core.publisher.Mono; |
|
||||||
|
|
||||||
import org.springframework.core.convert.TypeDescriptor; |
|
||||||
import org.springframework.core.convert.converter.GenericConverter; |
|
||||||
|
|
||||||
/** |
|
||||||
* Converter to adapt {@link CompletableFuture} to Reactive Streams and |
|
||||||
* Reactor {@link Mono}. |
|
||||||
* |
|
||||||
* @author Sebastien Deleuze |
|
||||||
* @since 5.0 |
|
||||||
*/ |
|
||||||
public class MonoToCompletableFutureConverter implements GenericConverter { |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() { |
|
||||||
Set<GenericConverter.ConvertiblePair> pairs = new LinkedHashSet<>(2); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Mono.class, CompletableFuture.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(CompletableFuture.class, Mono.class)); |
|
||||||
return pairs; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { |
|
||||||
if (source == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
else if (CompletableFuture.class.isAssignableFrom(sourceType.getType())) { |
|
||||||
return Mono.fromFuture((CompletableFuture<?>) source); |
|
||||||
} |
|
||||||
else if (CompletableFuture.class.isAssignableFrom(targetType.getType())) { |
|
||||||
return Mono.from((Publisher<?>) source).toFuture(); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,81 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.core.convert.support; |
|
||||||
|
|
||||||
import java.util.LinkedHashSet; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import org.reactivestreams.Publisher; |
|
||||||
import reactor.adapter.RxJava1Adapter; |
|
||||||
import reactor.core.publisher.Flux; |
|
||||||
import reactor.core.publisher.Mono; |
|
||||||
import rx.Completable; |
|
||||||
import rx.Observable; |
|
||||||
import rx.Single; |
|
||||||
|
|
||||||
import org.springframework.core.convert.TypeDescriptor; |
|
||||||
import org.springframework.core.convert.converter.GenericConverter; |
|
||||||
|
|
||||||
/** |
|
||||||
* Converter to adapt RxJava1 {@link Observable}, {@link Single}, and |
|
||||||
* {@link Completable} to Reactive Streams and Reactor types. |
|
||||||
* |
|
||||||
* @author Stephane Maldini |
|
||||||
* @author Sebastien Deleuze |
|
||||||
* @since 5.0 |
|
||||||
*/ |
|
||||||
public final class ReactorToRxJava1Converter implements GenericConverter { |
|
||||||
|
|
||||||
@Override |
|
||||||
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() { |
|
||||||
Set<GenericConverter.ConvertiblePair> pairs = new LinkedHashSet<>(6); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Flux.class, Observable.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Observable.class, Flux.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Mono.class, Single.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Single.class, Mono.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Mono.class, Completable.class)); |
|
||||||
pairs.add(new GenericConverter.ConvertiblePair(Completable.class, Mono.class)); |
|
||||||
return pairs; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { |
|
||||||
if (source == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
if (Observable.class.isAssignableFrom(sourceType.getType())) { |
|
||||||
return RxJava1Adapter.observableToFlux((Observable<?>) source); |
|
||||||
} |
|
||||||
else if (Observable.class.isAssignableFrom(targetType.getType())) { |
|
||||||
return RxJava1Adapter.publisherToObservable((Publisher<?>) source); |
|
||||||
} |
|
||||||
else if (Single.class.isAssignableFrom(sourceType.getType())) { |
|
||||||
return RxJava1Adapter.singleToMono((Single<?>) source); |
|
||||||
} |
|
||||||
else if (Single.class.isAssignableFrom(targetType.getType())) { |
|
||||||
return RxJava1Adapter.publisherToSingle((Publisher<?>) source); |
|
||||||
} |
|
||||||
else if (Completable.class.isAssignableFrom(sourceType.getType())) { |
|
||||||
return RxJava1Adapter.completableToMono((Completable) source); |
|
||||||
} |
|
||||||
else if (Completable.class.isAssignableFrom(targetType.getType())) { |
|
||||||
return RxJava1Adapter.publisherToCompletable((Publisher<?>) source); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2016 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.core.convert.support; |
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture; |
|
||||||
|
|
||||||
import org.junit.Before; |
|
||||||
import org.junit.Test; |
|
||||||
import org.reactivestreams.Publisher; |
|
||||||
import reactor.core.publisher.Flux; |
|
||||||
import reactor.core.publisher.Mono; |
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse; |
|
||||||
import static org.junit.Assert.assertTrue; |
|
||||||
|
|
||||||
/** |
|
||||||
* Unit tests for {@link ReactorToRxJava1Converter}. |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
*/ |
|
||||||
public class MonoToCompletableFutureConverterTests { |
|
||||||
|
|
||||||
private GenericConversionService conversionService; |
|
||||||
|
|
||||||
|
|
||||||
@Before |
|
||||||
public void setUp() throws Exception { |
|
||||||
this.conversionService = new GenericConversionService(); |
|
||||||
this.conversionService.addConverter(new MonoToCompletableFutureConverter()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void canConvert() throws Exception { |
|
||||||
assertTrue(this.conversionService.canConvert(Mono.class, CompletableFuture.class)); |
|
||||||
assertTrue(this.conversionService.canConvert(CompletableFuture.class, Mono.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Flux.class, CompletableFuture.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(CompletableFuture.class, Flux.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Publisher.class, CompletableFuture.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(CompletableFuture.class, Publisher.class)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,80 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2016 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.core.convert.support; |
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
import org.reactivestreams.Publisher; |
||||||
|
import reactor.core.publisher.Flux; |
||||||
|
import reactor.core.publisher.Mono; |
||||||
|
import rx.Completable; |
||||||
|
import rx.Observable; |
||||||
|
import rx.Single; |
||||||
|
|
||||||
|
import org.springframework.core.ReactiveAdapter; |
||||||
|
import org.springframework.core.ReactiveAdapterRegistry; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests for {@link ReactiveAdapterRegistry}. |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
*/ |
||||||
|
public class ReactiveAdapterRegistryTests { |
||||||
|
|
||||||
|
private ReactiveAdapterRegistry adapterRegistry; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() throws Exception { |
||||||
|
this.adapterRegistry = new ReactiveAdapterRegistry(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getDefaultAdapters() throws Exception { |
||||||
|
testMonoAdapter(Mono.class); |
||||||
|
testFluxAdapter(Flux.class); |
||||||
|
testFluxAdapter(Publisher.class); |
||||||
|
testMonoAdapter(CompletableFuture.class); |
||||||
|
testFluxAdapter(Observable.class); |
||||||
|
testMonoAdapter(Single.class); |
||||||
|
testMonoAdapter(Completable.class); |
||||||
|
} |
||||||
|
|
||||||
|
private void testFluxAdapter(Class<?> adapteeType) { |
||||||
|
ReactiveAdapter adapter = this.adapterRegistry.getAdapterFrom(adapteeType); |
||||||
|
assertNotNull(adapter); |
||||||
|
assertTrue(adapter.getDescriptor().isMultiValue()); |
||||||
|
|
||||||
|
adapter = this.adapterRegistry.getAdapterTo(adapteeType); |
||||||
|
assertNotNull(adapter); |
||||||
|
assertTrue(adapter.getDescriptor().isMultiValue()); |
||||||
|
} |
||||||
|
|
||||||
|
private void testMonoAdapter(Class<?> adapteeType) { |
||||||
|
ReactiveAdapter adapter = this.adapterRegistry.getAdapterFrom(adapteeType); |
||||||
|
assertNotNull(adapter); |
||||||
|
assertFalse(adapter.getDescriptor().isMultiValue()); |
||||||
|
|
||||||
|
adapter = this.adapterRegistry.getAdapterTo(adapteeType); |
||||||
|
assertNotNull(adapter); |
||||||
|
assertFalse(adapter.getDescriptor().isMultiValue()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,69 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2016 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.core.convert.support; |
|
||||||
|
|
||||||
import org.junit.Before; |
|
||||||
import org.junit.Test; |
|
||||||
import org.reactivestreams.Publisher; |
|
||||||
import reactor.core.publisher.Flux; |
|
||||||
import reactor.core.publisher.Mono; |
|
||||||
import rx.Completable; |
|
||||||
import rx.Observable; |
|
||||||
import rx.Single; |
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse; |
|
||||||
import static org.junit.Assert.assertTrue; |
|
||||||
|
|
||||||
/** |
|
||||||
* Unit tests for {@link ReactorToRxJava1Converter}. |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
*/ |
|
||||||
public class ReactorToRxJava1ConverterTests { |
|
||||||
|
|
||||||
private GenericConversionService conversionService; |
|
||||||
|
|
||||||
|
|
||||||
@Before |
|
||||||
public void setUp() throws Exception { |
|
||||||
this.conversionService = new GenericConversionService(); |
|
||||||
this.conversionService.addConverter(new ReactorToRxJava1Converter()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void canConvert() throws Exception { |
|
||||||
assertTrue(this.conversionService.canConvert(Flux.class, Observable.class)); |
|
||||||
assertTrue(this.conversionService.canConvert(Observable.class, Flux.class)); |
|
||||||
|
|
||||||
assertTrue(this.conversionService.canConvert(Mono.class, Single.class)); |
|
||||||
assertTrue(this.conversionService.canConvert(Single.class, Mono.class)); |
|
||||||
|
|
||||||
assertTrue(this.conversionService.canConvert(Mono.class, Completable.class)); |
|
||||||
assertTrue(this.conversionService.canConvert(Completable.class, Mono.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Flux.class, Single.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(Single.class, Flux.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Flux.class, Completable.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(Completable.class, Flux.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Mono.class, Observable.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(Observable.class, Mono.class)); |
|
||||||
|
|
||||||
assertFalse(this.conversionService.canConvert(Publisher.class, Observable.class)); |
|
||||||
assertFalse(this.conversionService.canConvert(Observable.class, Publisher.class)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue