/* * Copyright 2016-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. * 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.data.repository.util; import static org.springframework.data.repository.util.ReactiveWrapperConverters.RegistryHolder.*; import io.reactivex.BackpressureStrategy; import io.reactivex.Flowable; import io.reactivex.Maybe; import lombok.experimental.UtilityClass; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import rx.Completable; import rx.Observable; import rx.Single; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.repository.util.ReactiveWrappers.ReactiveLibrary; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * Conversion support for reactive wrapper types. This class is a reactive extension to * {@link QueryExecutionConverters}. * <p> * This class discovers reactive wrapper availability and their conversion support based on the class path. Reactive * wrapper types might be supported/on the class path but conversion may require additional dependencies. * * @author Mark Paluch * @author Oliver Gierke * @since 2.0 * @see ReactiveWrappers * @see ReactiveAdapterRegistry */ @UtilityClass public class ReactiveWrapperConverters { private static final List<ReactiveTypeWrapper<?>> REACTIVE_WRAPPERS = new ArrayList<>(); private static final GenericConversionService GENERIC_CONVERSION_SERVICE = new GenericConversionService(); static { if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA1)) { REACTIVE_WRAPPERS.add(RxJava1SingleWrapper.INSTANCE); REACTIVE_WRAPPERS.add(RxJava1ObservableWrapper.INSTANCE); } if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA2)) { REACTIVE_WRAPPERS.add(RxJava2SingleWrapper.INSTANCE); REACTIVE_WRAPPERS.add(RxJava2MaybeWrapper.INSTANCE); REACTIVE_WRAPPERS.add(RxJava2ObservableWrapper.INSTANCE); REACTIVE_WRAPPERS.add(RxJava2FlowableWrapper.INSTANCE); } if (ReactiveWrappers.isAvailable(ReactiveLibrary.PROJECT_REACTOR)) { REACTIVE_WRAPPERS.add(FluxWrapper.INSTANCE); REACTIVE_WRAPPERS.add(MonoWrapper.INSTANCE); REACTIVE_WRAPPERS.add(PublisherWrapper.INSTANCE); } registerConvertersIn(GENERIC_CONVERSION_SERVICE); } /** * Registers converters for wrapper types found on the classpath. * * @param conversionService must not be {@literal null}. */ private static ConversionService registerConvertersIn(ConfigurableConversionService conversionService) { Assert.notNull(conversionService, "ConversionService must not be null!"); if (ReactiveWrappers.isAvailable(ReactiveLibrary.PROJECT_REACTOR)) { if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA1)) { conversionService.addConverter(PublisherToRxJava1CompletableConverter.INSTANCE); conversionService.addConverter(RxJava1CompletableToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava1CompletableToMonoConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava1SingleConverter.INSTANCE); conversionService.addConverter(RxJava1SingleToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava1SingleToMonoConverter.INSTANCE); conversionService.addConverter(RxJava1SingleToFluxConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava1ObservableConverter.INSTANCE); conversionService.addConverter(RxJava1ObservableToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava1ObservableToMonoConverter.INSTANCE); conversionService.addConverter(RxJava1ObservableToFluxConverter.INSTANCE); } if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA2)) { conversionService.addConverter(PublisherToRxJava2CompletableConverter.INSTANCE); conversionService.addConverter(RxJava2CompletableToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava2CompletableToMonoConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava2SingleConverter.INSTANCE); conversionService.addConverter(RxJava2SingleToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava2SingleToMonoConverter.INSTANCE); conversionService.addConverter(RxJava2SingleToFluxConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava2ObservableConverter.INSTANCE); conversionService.addConverter(RxJava2ObservableToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava2ObservableToMonoConverter.INSTANCE); conversionService.addConverter(RxJava2ObservableToFluxConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava2FlowableConverter.INSTANCE); conversionService.addConverter(RxJava2FlowableToPublisherConverter.INSTANCE); conversionService.addConverter(PublisherToRxJava2MaybeConverter.INSTANCE); conversionService.addConverter(RxJava2MaybeToPublisherConverter.INSTANCE); conversionService.addConverter(RxJava2MaybeToMonoConverter.INSTANCE); conversionService.addConverter(RxJava2MaybeToFluxConverter.INSTANCE); } conversionService.addConverter(PublisherToMonoConverter.INSTANCE); conversionService.addConverter(PublisherToFluxConverter.INSTANCE); if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA1)) { conversionService.addConverter(RxJava1SingleToObservableConverter.INSTANCE); conversionService.addConverter(RxJava1ObservableToSingleConverter.INSTANCE); } if (ReactiveWrappers.isAvailable(ReactiveLibrary.RXJAVA2)) { conversionService.addConverter(RxJava2SingleToObservableConverter.INSTANCE); conversionService.addConverter(RxJava2ObservableToSingleConverter.INSTANCE); conversionService.addConverter(RxJava2ObservableToMaybeConverter.INSTANCE); } } return conversionService; } /** * Returns whether the given type is supported for wrapper type conversion. * <p> * NOTE: A reactive wrapper type might be supported in general by {@link ReactiveWrappers#supports(Class)} but not * necessarily for conversion using this method. * </p> * * @param type must not be {@literal null}. * @return {@literal true} if the {@code type} is a supported reactive wrapper type. */ public static boolean supports(Class<?> type) { return RegistryHolder.REACTIVE_ADAPTER_REGISTRY != null && RegistryHolder.REACTIVE_ADAPTER_REGISTRY.getAdapter(type) != null; } /** * Casts or adopts the given wrapper type to a target wrapper type. * * @param reactiveObject the stream, must not be {@literal null}. * @param targetWrapperType must not be {@literal null}. * @return */ @SuppressWarnings("unchecked") public static <T> T toWrapper(Object reactiveObject, Class<? extends T> targetWrapperType) { Assert.notNull(reactiveObject, "Reactive source object must not be null!"); Assert.notNull(targetWrapperType, "Reactive target type must not be null!"); if (targetWrapperType.isAssignableFrom(reactiveObject.getClass())) { return (T) reactiveObject; } return GENERIC_CONVERSION_SERVICE.convert(reactiveObject, targetWrapperType); } /** * Maps elements of a reactive element stream to other elements. * * @param reactiveObject must not be {@literal null}. * @param converter must not be {@literal null}. * @return */ @SuppressWarnings("unchecked") public static <T> T map(Object reactiveObject, Function<Object, Object> converter) { Assert.notNull(reactiveObject, "Reactive source object must not be null!"); Assert.notNull(converter, "Converter must not be null!"); return REACTIVE_WRAPPERS.stream()// .filter(it -> ClassUtils.isAssignable(it.getWrapperClass(), reactiveObject.getClass()))// .findFirst()// .map(it -> (T) it.map(reactiveObject, converter))// .orElseThrow(() -> new IllegalStateException(String.format("Cannot apply converter to %s", reactiveObject))); } /** * Return {@literal true} if objects of {@code sourceType} can be converted to the {@code targetType}. * * @param sourceType must not be {@literal null}. * @param targetType must not be {@literal null}. * @return {@literal true} if a conversion can be performed. */ public static boolean canConvert(Class<?> sourceType, Class<?> targetType) { Assert.notNull(sourceType, "Source type must not be null!"); Assert.notNull(targetType, "Target type must not be null!"); return GENERIC_CONVERSION_SERVICE.canConvert(sourceType, targetType); } // ------------------------------------------------------------------------- // Wrapper descriptors // ------------------------------------------------------------------------- /** * Wrapper descriptor that can apply a {@link Function} to map items inside its stream. * * @author Mark Paluch * @author Christoph Strobl */ private interface ReactiveTypeWrapper<T> { /** * @return the wrapper class. */ Class<? super T> getWrapperClass(); /** * Apply a {@link Function} to a reactive type. * * @param wrapper the reactive type, must not be {@literal null}. * @param function the converter, must not be {@literal null}. * @return the reactive type applying conversion. */ Object map(Object wrapper, Function<Object, Object> function); } /** * Wrapper for Project Reactor's {@link Mono}. */ private enum MonoWrapper implements ReactiveTypeWrapper<Mono<?>> { INSTANCE; @Override public Class<? super Mono<?>> getWrapperClass() { return Mono.class; } @Override public Mono<?> map(Object wrapper, Function<Object, Object> function) { return ((Mono<?>) wrapper).map(function::apply); } } /** * Wrapper for Project Reactor's {@link Flux}. */ private enum FluxWrapper implements ReactiveTypeWrapper<Flux<?>> { INSTANCE; @Override public Class<? super Flux<?>> getWrapperClass() { return Flux.class; } public Flux<?> map(Object wrapper, Function<Object, Object> function) { return ((Flux<?>) wrapper).map(function::apply); } } /** * Wrapper for Reactive Stream's {@link Publisher}. */ private enum PublisherWrapper implements ReactiveTypeWrapper<Publisher<?>> { INSTANCE; @Override public Class<? super Publisher<?>> getWrapperClass() { return Publisher.class; } @Override public Publisher<?> map(Object wrapper, Function<Object, Object> function) { if (wrapper instanceof Mono) { return MonoWrapper.INSTANCE.map(wrapper, function); } if (wrapper instanceof Flux) { return FluxWrapper.INSTANCE.map(wrapper, function); } return FluxWrapper.INSTANCE.map(Flux.from((Publisher<?>) wrapper), function); } } /** * Wrapper for RxJava 1's {@link Single}. */ private enum RxJava1SingleWrapper implements ReactiveTypeWrapper<Single<?>> { INSTANCE; @Override public Class<? super Single<?>> getWrapperClass() { return Single.class; } @Override public Single<?> map(Object wrapper, Function<Object, Object> function) { return ((Single<?>) wrapper).map(function::apply); } } /** * Wrapper for RxJava 1's {@link Observable}. */ private enum RxJava1ObservableWrapper implements ReactiveTypeWrapper<Observable<?>> { INSTANCE; @Override public Class<? super Observable<?>> getWrapperClass() { return Observable.class; } @Override public Observable<?> map(Object wrapper, Function<Object, Object> function) { return ((Observable<?>) wrapper).map(function::apply); } } /** * Wrapper for RxJava 2's {@link io.reactivex.Single}. */ private enum RxJava2SingleWrapper implements ReactiveTypeWrapper<io.reactivex.Single<?>> { INSTANCE; @Override public Class<? super io.reactivex.Single<?>> getWrapperClass() { return io.reactivex.Single.class; } @Override public io.reactivex.Single<?> map(Object wrapper, Function<Object, Object> function) { return ((io.reactivex.Single<?>) wrapper).map(function::apply); } } /** * Wrapper for RxJava 2's {@link io.reactivex.Maybe}. */ private enum RxJava2MaybeWrapper implements ReactiveTypeWrapper<Maybe<?>> { INSTANCE; @Override public Class<? super io.reactivex.Maybe<?>> getWrapperClass() { return io.reactivex.Maybe.class; } @Override public io.reactivex.Maybe<?> map(Object wrapper, Function<Object, Object> function) { return ((io.reactivex.Maybe<?>) wrapper).map(function::apply); } } /** * Wrapper for RxJava 2's {@link io.reactivex.Observable}. */ private enum RxJava2ObservableWrapper implements ReactiveTypeWrapper<io.reactivex.Observable<?>> { INSTANCE; @Override public Class<? super io.reactivex.Observable<?>> getWrapperClass() { return io.reactivex.Observable.class; } @Override public io.reactivex.Observable<?> map(Object wrapper, Function<Object, Object> function) { return ((io.reactivex.Observable<?>) wrapper).map(function::apply); } } /** * Wrapper for RxJava 2's {@link io.reactivex.Flowable}. */ private enum RxJava2FlowableWrapper implements ReactiveTypeWrapper<Flowable<?>> { INSTANCE; @Override public Class<? super Flowable<?>> getWrapperClass() { return io.reactivex.Flowable.class; } @Override public io.reactivex.Flowable<?> map(Object wrapper, Function<Object, Object> function) { return ((io.reactivex.Flowable<?>) wrapper).map(function::apply); } } // ------------------------------------------------------------------------- // ReactiveStreams converters // ------------------------------------------------------------------------- /** * A {@link Converter} to convert a {@link Publisher} to {@link Flux}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToFluxConverter implements Converter<Publisher<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(Publisher<?> source) { return Flux.from(source); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToMonoConverter implements Converter<Publisher<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(Publisher<?> source) { return Mono.from(source); } } // ------------------------------------------------------------------------- // RxJava 1 converters // ------------------------------------------------------------------------- /** * A {@link Converter} to convert a {@link Publisher} to {@link Single}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava1SingleConverter implements Converter<Publisher<?>, Single<?>> { INSTANCE; @Override public Single<?> convert(Publisher<?> source) { return (Single<?>) REACTIVE_ADAPTER_REGISTRY.getAdapter(Single.class).fromPublisher(Mono.from(source)); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link Completable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava1CompletableConverter implements Converter<Publisher<?>, Completable> { INSTANCE; @Override public Completable convert(Publisher<?> source) { return (Completable) REACTIVE_ADAPTER_REGISTRY.getAdapter(Completable.class).fromPublisher(source); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link Observable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava1ObservableConverter implements Converter<Publisher<?>, Observable<?>> { INSTANCE; @Override public Observable<?> convert(Publisher<?> source) { return (Observable<?>) REACTIVE_ADAPTER_REGISTRY.getAdapter(Observable.class).fromPublisher(Flux.from(source)); } } /** * A {@link Converter} to convert a {@link Single} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1SingleToPublisherConverter implements Converter<Single<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(Single<?> source) { return Flux.defer(() -> REACTIVE_ADAPTER_REGISTRY.getAdapter(Single.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link Single} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1SingleToMonoConverter implements Converter<Single<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(Single<?> source) { return Mono.defer(() -> Mono.from(REACTIVE_ADAPTER_REGISTRY.getAdapter(Single.class).toPublisher(source))); } } /** * A {@link Converter} to convert a {@link Single} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1SingleToFluxConverter implements Converter<Single<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(Single<?> source) { return Flux.defer(() -> REACTIVE_ADAPTER_REGISTRY.getAdapter(Single.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link Completable} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1CompletableToPublisherConverter implements Converter<Completable, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(Completable source) { return Flux.defer(() -> REACTIVE_ADAPTER_REGISTRY.getAdapter(Completable.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link Completable} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1CompletableToMonoConverter implements Converter<Completable, Mono<?>> { INSTANCE; @Override public Mono<?> convert(Completable source) { return Mono.from(RxJava1CompletableToPublisherConverter.INSTANCE.convert(source)); } } /** * A {@link Converter} to convert an {@link Observable} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1ObservableToPublisherConverter implements Converter<Observable<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(Observable<?> source) { return Flux.defer(() -> REACTIVE_ADAPTER_REGISTRY.getAdapter(Observable.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link Observable} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1ObservableToMonoConverter implements Converter<Observable<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(Observable<?> source) { return Mono.defer(() -> Mono.from(REACTIVE_ADAPTER_REGISTRY.getAdapter(Observable.class).toPublisher(source))); } } /** * A {@link Converter} to convert a {@link Observable} to {@link Flux}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1ObservableToFluxConverter implements Converter<Observable<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(Observable<?> source) { return Flux.defer(() -> REACTIVE_ADAPTER_REGISTRY.getAdapter(Observable.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link Observable} to {@link Single}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1ObservableToSingleConverter implements Converter<Observable<?>, Single<?>> { INSTANCE; @Override public Single<?> convert(Observable<?> source) { return source.toSingle(); } } /** * A {@link Converter} to convert a {@link Single} to {@link Single}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava1SingleToObservableConverter implements Converter<Single<?>, Observable<?>> { INSTANCE; @Override public Observable<?> convert(Single<?> source) { return source.toObservable(); } } // ------------------------------------------------------------------------- // RxJava 2 converters // ------------------------------------------------------------------------- /** * A {@link Converter} to convert a {@link Publisher} to {@link io.reactivex.Single}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava2SingleConverter implements Converter<Publisher<?>, io.reactivex.Single<?>> { INSTANCE; @Override public io.reactivex.Single<?> convert(Publisher<?> source) { return (io.reactivex.Single<?>) REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Single.class) .fromPublisher(source); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link io.reactivex.Completable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava2CompletableConverter implements Converter<Publisher<?>, io.reactivex.Completable> { INSTANCE; @Override public io.reactivex.Completable convert(Publisher<?> source) { return (io.reactivex.Completable) REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Completable.class) .fromPublisher(source); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link io.reactivex.Observable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava2ObservableConverter implements Converter<Publisher<?>, io.reactivex.Observable<?>> { INSTANCE; @Override public io.reactivex.Observable<?> convert(Publisher<?> source) { return (io.reactivex.Observable<?>) REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Observable.class) .fromPublisher(source); } } /** * A {@link Converter} to convert a {@link io.reactivex.Single} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2SingleToPublisherConverter implements Converter<io.reactivex.Single<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(io.reactivex.Single<?> source) { return REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Single.class).toPublisher(source); } } /** * A {@link Converter} to convert a {@link io.reactivex.Single} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2SingleToMonoConverter implements Converter<io.reactivex.Single<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(io.reactivex.Single<?> source) { return Mono.from(REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Single.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link io.reactivex.Single} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2SingleToFluxConverter implements Converter<io.reactivex.Single<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(io.reactivex.Single<?> source) { return Flux.from(REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Single.class).toPublisher(source)); } } /** * A {@link Converter} to convert a {@link io.reactivex.Completable} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2CompletableToPublisherConverter implements Converter<io.reactivex.Completable, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(io.reactivex.Completable source) { return REACTIVE_ADAPTER_REGISTRY.getAdapter(io.reactivex.Completable.class).toPublisher(source); } } /** * A {@link Converter} to convert a {@link io.reactivex.Completable} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2CompletableToMonoConverter implements Converter<io.reactivex.Completable, Mono<?>> { INSTANCE; @Override public Mono<?> convert(io.reactivex.Completable source) { return Mono.from(RxJava2CompletableToPublisherConverter.INSTANCE.convert(source)); } } /** * A {@link Converter} to convert an {@link io.reactivex.Observable} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2ObservableToPublisherConverter implements Converter<io.reactivex.Observable<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(io.reactivex.Observable<?> source) { return source.toFlowable(BackpressureStrategy.BUFFER); } } /** * A {@link Converter} to convert a {@link io.reactivex.Observable} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2ObservableToMonoConverter implements Converter<io.reactivex.Observable<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(io.reactivex.Observable<?> source) { return Mono.from(source.toFlowable(BackpressureStrategy.BUFFER)); } } /** * A {@link Converter} to convert a {@link io.reactivex.Observable} to {@link Flux}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2ObservableToFluxConverter implements Converter<io.reactivex.Observable<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(io.reactivex.Observable<?> source) { return Flux.from(source.toFlowable(BackpressureStrategy.BUFFER)); } } /** * A {@link Converter} to convert a {@link Publisher} to {@link io.reactivex.Flowable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava2FlowableConverter implements Converter<Publisher<?>, io.reactivex.Flowable<?>> { INSTANCE; @Override public io.reactivex.Flowable<?> convert(Publisher<?> source) { return Flowable.fromPublisher(source); } } /** * A {@link Converter} to convert a {@link io.reactivex.Flowable} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2FlowableToPublisherConverter implements Converter<io.reactivex.Flowable<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(io.reactivex.Flowable<?> source) { return source; } } /** * A {@link Converter} to convert a {@link Publisher} to {@link io.reactivex.Flowable}. * * @author Mark Paluch * @author 2.0 */ private enum PublisherToRxJava2MaybeConverter implements Converter<Publisher<?>, io.reactivex.Maybe<?>> { INSTANCE; @Override public io.reactivex.Maybe<?> convert(Publisher<?> source) { return (io.reactivex.Maybe<?>) REACTIVE_ADAPTER_REGISTRY.getAdapter(Maybe.class).fromPublisher(source); } } /** * A {@link Converter} to convert a {@link io.reactivex.Maybe} to {@link Publisher}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2MaybeToPublisherConverter implements Converter<io.reactivex.Maybe<?>, Publisher<?>> { INSTANCE; @Override public Publisher<?> convert(io.reactivex.Maybe<?> source) { return source.toFlowable(); } } /** * A {@link Converter} to convert a {@link io.reactivex.Maybe} to {@link Mono}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2MaybeToMonoConverter implements Converter<io.reactivex.Maybe<?>, Mono<?>> { INSTANCE; @Override public Mono<?> convert(io.reactivex.Maybe<?> source) { return Mono.from(source.toFlowable()); } } /** * A {@link Converter} to convert a {@link io.reactivex.Maybe} to {@link Flux}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2MaybeToFluxConverter implements Converter<io.reactivex.Maybe<?>, Flux<?>> { INSTANCE; @Override public Flux<?> convert(io.reactivex.Maybe<?> source) { return Flux.from(source.toFlowable()); } } /** * A {@link Converter} to convert a {@link Observable} to {@link Single}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2ObservableToSingleConverter implements Converter<io.reactivex.Observable<?>, io.reactivex.Single<?>> { INSTANCE; @Override public io.reactivex.Single<?> convert(io.reactivex.Observable<?> source) { return source.singleOrError(); } } /** * A {@link Converter} to convert a {@link Observable} to {@link Maybe}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2ObservableToMaybeConverter implements Converter<io.reactivex.Observable<?>, io.reactivex.Maybe<?>> { INSTANCE; @Override public io.reactivex.Maybe<?> convert(io.reactivex.Observable<?> source) { return source.singleElement(); } } /** * A {@link Converter} to convert a {@link Single} to {@link Single}. * * @author Mark Paluch * @author 2.0 */ private enum RxJava2SingleToObservableConverter implements Converter<io.reactivex.Single<?>, io.reactivex.Observable<?>> { INSTANCE; @Override public io.reactivex.Observable<?> convert(io.reactivex.Single<?> source) { return source.toObservable(); } } /** * Holder for delayed initialization of {@link ReactiveAdapterRegistry}. * * @author Mark Paluch * @author 2.0 */ static class RegistryHolder { static final ReactiveAdapterRegistry REACTIVE_ADAPTER_REGISTRY; static { if (ReactiveWrappers.isAvailable(ReactiveLibrary.PROJECT_REACTOR)) { REACTIVE_ADAPTER_REGISTRY = new ReactiveAdapterRegistry(); } else { REACTIVE_ADAPTER_REGISTRY = null; } } } }