All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hu.akarnokd.rxjava2.interop.ObservableInterop Maven / Gradle / Ivy

/*
 * Copyright 2016 David Karnok
 *
 * 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 hu.akarnokd.rxjava2.interop;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;
import io.reactivex.functions.Function;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.subjects.AsyncSubject;

/**
 * Utility methods, sources and operators supporting RxJava 2 and the Jdk 8 API
 * interoperation.
 * 
 * @since 0.1.0
 */
public final class ObservableInterop {

    /** Utility class. */
    private ObservableInterop() {
        throw new IllegalStateException("No instances!");
    }

    /**
     * Wrap a Stream into a Observable.
     * 

Note that Streams can only be consumed once and non-concurrently. * @param the value type * @param stream the source Stream * @return the new Observable instance */ public static Observable fromStream(Stream stream) { return Observable.fromIterable(() -> stream.iterator()); } /** * Returns a Observable for the value (or lack of) in the given Optional. * @param the value type * @param opt the optional to wrap * @return the new Observable instance */ public static Observable fromOptional(Optional opt) { return opt.map(Observable::just).orElse(Observable.empty()); } /** * Create a Observable that signals the terminal value or error of the given * CompletionStage. *

Cancelling the Observable subscription doesn't cancel the CompletionStage. * @param the value type * @param cs the CompletionStage instance * @return the new Observable instance */ public static Observable fromFuture(CompletionStage cs) { AsyncSubject ap = AsyncSubject.create(); cs.whenComplete((v, e) -> { if (e != null) { ap.onError(e); } else { ap.onNext(v); ap.onComplete(); } }); return ap; } /** * Collect the elements of the Observable via the help of Collector and its callback * functions. * @param the upstream value type * @param the accumulated type * @param the result type * @param collector the Collector object providing the callbacks * @return the Transformer instance to be used with {@code Observable.compose()} */ public static ObservableTransformer collect(Collector collector) { return f -> RxJavaPlugins.onAssembly(new ObservableCollector<>(f, collector)); } /** * Returns a CompletionStage that signals the first element of the Observable * or a NoSuchElementException if the Observable is empty. * @param the value type * @return the Function to be used via {@code Observable.to}. */ public static Function, CompletionStage> first() { return f -> { CompletableFuture cf = new CompletableFuture<>(); f.firstOrError().subscribe(cf::complete, cf::completeExceptionally); return cf; }; } /** * Returns a CompletionStage that signals the single element of the Observable, * IllegalArgumentException if the Observable is longer than 1 element * or a NoSuchElementException if the Observable is empty. * @param the value type * @return the Function to be used with {@code Observable.to}. */ public static Function, CompletionStage> single() { return f -> { CompletableFuture cf = new CompletableFuture<>(); f.singleOrError().subscribe(cf::complete, cf::completeExceptionally); return cf; }; } /** * Returns a CompletionStage that emits the last element of the Observable or * NoSuchElementException if the Observable is empty. * @param the value type * @return the Function to be used with {@code Observable.to}. */ public static Function, CompletionStage> last() { return f -> { CompletableFuture cf = new CompletableFuture<>(); f.lastOrError().subscribe(cf::complete, cf::completeExceptionally); return cf; }; } /** * Returns a blocking Stream of the elements of the Observable. *

* Closing the Stream will cancel the flow. * @param the value type * @return the Function to be used with {@code Observable.to}. */ public static Function, Stream> toStream() { return f -> ZeroOneIterator.toStream(f.blockingIterable().iterator()); } /** * Block until the source Observable emits its first item and return that as Optional. * @param the value type * @return the converter Function to be used with {@code Observable.to()}. */ public static Function, Optional> firstElement() { return o -> Optional.ofNullable(o.blockingFirst(null)); } /** * Block until the source Observable completes and return its last value as Optional. * @param the value type * @return the converter Function to be used with {@code Observable.to()}. */ public static Function, Optional> lastElement() { return o -> Optional.ofNullable(o.blockingLast(null)); } /** * Maps the upstream value into an optional and extracts its optional value to be emitted towards * the downstream if present. * @param the upstream value type * @param the result value type * @param mapper the function receiving the upstream value and should return an Optional * @return the Transformer instance to be used with {@code Observable.compose()} */ public static ObservableTransformer mapOptional(Function> mapper) { return f -> RxJavaPlugins.onAssembly(new ObservableMapOptional<>(f, mapper)); } /** * Map each value of the upstream into a Stream and flatten them into a single sequence. * @param the input value type * @param the Stream type * @param mapper the function that returns a Stream for each upstream value * @return the new Transformer instance */ public static ObservableTransformer flatMapStream(Function> mapper) { return o -> o.flatMapIterable(v -> { Iterator it = mapper.apply(v).iterator(); return () -> it; }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy