/* * Copyright 2016 The Simple File Server 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.sfs.rx; import io.vertx.core.AsyncResult; import io.vertx.core.Context; import io.vertx.core.Handler; import io.vertx.core.Vertx; import org.sfs.SfsVertx; import rx.Observable; import rx.Observer; import rx.Scheduler; import rx.Subscriber; import rx.functions.Action0; import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func1; import rx.functions.Func2; import rx.functions.Func3; import rx.functions.Func4; import rx.functions.Func5; import rx.functions.Func6; import rx.functions.Func7; import rx.functions.Func8; import rx.functions.Func9; import rx.functions.FuncN; import rx.plugins.RxJavaSchedulersHook; import java.util.List; import java.util.concurrent.ExecutorService; import static java.util.Arrays.asList; import static rx.Observable.combineLatestDelayError; import static rx.Observable.defer; import static rx.functions.Functions.fromFunc; public class RxHelper { @SuppressWarnings("unchecked") public static final <T1, T2, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Func2<? super T1, ? super T2, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Func3<? super T1, ? super T2, ? super T3, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Func4<? super T1, ? super T2, ? super T3, ? super T4, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, T5, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Observable<? extends T5> o5, Func5<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single(), o5.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, T5, T6, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Observable<? extends T5> o5, Observable<? extends T6> o6, Func6<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single(), o5.single(), o6.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, T5, T6, T7, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Observable<? extends T5> o5, Observable<? extends T6> o6, Observable<? extends T7> o7, Func7<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single(), o5.single(), o6.single(), o7.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, T5, T6, T7, T8, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Observable<? extends T5> o5, Observable<? extends T6> o6, Observable<? extends T7> o7, Observable<? extends T8> o8, Func8<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single(), o5.single(), o6.single(), o7.single(), o8.single()), fromFunc(combineFunction)); } @SuppressWarnings("unchecked") public static final <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> Observable<R> combineSinglesDelayError(Observable<? extends T1> o1, Observable<? extends T2> o2, Observable<? extends T3> o3, Observable<? extends T4> o4, Observable<? extends T5> o5, Observable<? extends T6> o6, Observable<? extends T7> o7, Observable<? extends T8> o8, Observable<? extends T9> o9, Func9<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? super T9, ? extends R> combineFunction) { return combineSinglesDelayError(asList(o1.single(), o2.single(), o3.single(), o4.single(), o5.single(), o6.single(), o7.single(), o8.single(), o9.single()), fromFunc(combineFunction)); } public static <T> Observable<T> executeBlocking(Context context, ExecutorService executorService, Func0<T> func0) { return Defer.aVoid() .flatMap(aVoid -> { ObservableFuture<T> observableFuture = RxHelper.observableFuture(); executorService.execute(() -> { try { T result = func0.call(); context.runOnContext(event -> observableFuture.complete(result)); } catch (Throwable e) { context.runOnContext(event -> observableFuture.fail(e)); } }); return observableFuture; }); } private static final <T, R> Observable<R> combineSinglesDelayError(List<? extends Observable<? extends T>> sources, FuncN<? extends R> combineFunction) { return combineLatestDelayError(sources, combineFunction); } public static <A> Observable<Boolean> iterate(Vertx vertx, final Iterable<? extends A> items, final Func1<A, Observable<Boolean>> func1) { ObservableFuture<Boolean> handler = RxHelper.observableFuture(); Observable.from(items) .concatMap(func1::call) .subscribe(new Subscriber<Boolean>() { Boolean result; @Override public void onStart() { request(1); } @Override public void onCompleted() { try { handler.complete(result); } finally { unsubscribe(); } } @Override public void onError(Throwable e) { handler.fail(e); } @Override public void onNext(Boolean _continue) { result = _continue; if (Boolean.TRUE.equals(_continue)) { request(1); } else { onCompleted(); } } }); return handler; } public static <T> ObservableFuture<T> observableFuture() { return new ObservableFuture<>(); } public static <T> Handler<AsyncResult<T>> toFuture(Observer<T> observer) { ObservableFuture<T> observable = RxHelper.<T>observableFuture(); observable.subscribe(observer); return observable.toHandler(); } public static <T> Handler<AsyncResult<T>> toFuture(Action1<T> onNext) { ObservableFuture<T> observable = RxHelper.<T>observableFuture(); observable.subscribe(onNext); return observable.toHandler(); } public static <T> Handler<AsyncResult<T>> toFuture(Action1<T> onNext, Action1<Throwable> onError) { ObservableFuture<T> observable = RxHelper.<T>observableFuture(); observable.subscribe(onNext, onError); return observable.toHandler(); } public static <T> Handler<AsyncResult<T>> toFuture(Action1<T> onNext, Action1<Throwable> onError, Action0 onComplete) { ObservableFuture<T> observable = RxHelper.<T>observableFuture(); observable.subscribe(onNext, onError, onComplete); return observable.toHandler(); } public static Scheduler scheduler(Vertx vertx) { return new ContextScheduler(vertx, false); } public static Scheduler scheduler(Context context) { return new ContextScheduler(context, false); } public static Scheduler blockingScheduler(Vertx vertx) { return new ContextScheduler(vertx, true); } public static Scheduler blockingScheduler(Vertx vertx, boolean ordered) { return new ContextScheduler(vertx, true, ordered); } public static RxJavaSchedulersHook schedulerHook(Context context) { return new RxJavaSchedulersHook() { @Override public Scheduler getComputationScheduler() { return scheduler(context); } @Override public Scheduler getIOScheduler() { return blockingScheduler(context.owner()); } @Override public Scheduler getNewThreadScheduler() { return scheduler(context); } }; } public static RxJavaSchedulersHook schedulerHook(Vertx vertx) { return new RxJavaSchedulersHook() { @Override public Scheduler getComputationScheduler() { return scheduler(vertx); } @Override public Scheduler getIOScheduler() { return blockingScheduler(vertx); } @Override public Scheduler getNewThreadScheduler() { return scheduler(vertx); } }; } }