io.reactivex.rxjavafx.transformers.FxObservableTransformers Maven / Gradle / Ivy
/**
* Copyright 2017 Netflix, Inc.
*
* 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 io.reactivex.rxjavafx.transformers;
import io.reactivex.ObservableOperator;
import io.reactivex.ObservableTransformer;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.observers.ResourceObserver;
import javafx.application.Platform;
public final class FxObservableTransformers {
private FxObservableTransformers() {}
private static void runOnFx(T t, Consumer consumer) {
Platform.runLater(() -> {
try {
consumer.accept(t);
} catch (Throwable e) {
throw Exceptions.propagate(e);
}
}
);
}
private static void runOnFx(Action action) {
Platform.runLater(() -> {
try {
action.run();
} catch (Throwable e) {
throw Exceptions.propagate(e);
}
}
);
}
/**
* Performs a given action for each item on the FX thread
* @param onNext
* @param
*/
public static ObservableTransformer doOnNextFx(Consumer onNext) {
return obs -> obs.doOnNext(t -> runOnFx(t, onNext));
}
/**
* Performs a given action on a Throwable on the FX thread in the event of an onError
* @param onError
* @param
*/
public static ObservableTransformer doOnErrorFx(Consumer onError) {
return obs -> obs.doOnError(e -> runOnFx(e,onError));
}
/**
* Performs a given Action on the FX thread when onCompleted is called
* @param onCompleted
* @param
*/
public static ObservableTransformer doOnCompleteFx(Action onCompleted) {
return obs -> obs.doOnComplete(() -> runOnFx(onCompleted));
}
/**
* Performs a given Action on the FX thread when subscribed to
* @param subscribe
* @param
*/
public static ObservableTransformer doOnSubscribeFx(Consumer subscribe) {
return obs -> obs.doOnSubscribe((d -> runOnFx(d,subscribe)));
}
/**
* Performs the provided onTerminate action on the FX thread
* @param onTerminate
* @param
*/
public static ObservableTransformer doOnTerminateFx(Action onTerminate) {
return obs -> obs.doOnTerminate(() -> runOnFx(onTerminate));
}
/**
* Performs the provided onTerminate action on the FX thread
* @param onDipsose
* @param
*/
public static ObservableTransformer doOnDisposeFx(Action onDipsose) {
return obs -> obs.doOnDispose(() -> runOnFx(onDipsose));
}
/**
* Performs an action on onNext with the provided emission count
* @param onNext
* @param
*/
public static ObservableTransformer doOnNextCount(Consumer onNext) {
return obs -> obs.lift(new OperatorEmissionCounter<>(new CountObserver(onNext,null,null)));
}
/**
* Performs an action on onComplete with the provided emission count
* @param onComplete
* @param
*/
public static ObservableTransformer doOnCompleteCount(Consumer onComplete) {
return obs -> obs.lift(new OperatorEmissionCounter<>(new CountObserver(null,onComplete,null)));
}
/**
* Performs an action on onError with the provided emission count
* @param onError
* @param
*/
public static ObservableTransformer doOnErrorCount(Consumer onError) {
return obs -> obs.lift(new OperatorEmissionCounter<>(new CountObserver(null,null,onError)));
}
/**
* Performs an action on FX thread on onNext with the provided emission count
* @param onNext
* @param
*/
public static ObservableTransformer doOnNextCountFx(Consumer onNext) {
return obs -> obs.compose(doOnNextCount(i -> runOnFx(i,onNext)));
}
/**
* Performs an action on FX thread on onCompleted with the provided emission count
* @param onComplete
* @param
*/
public static ObservableTransformer doOnCompleteCountFx(Consumer onComplete) {
return obs -> obs.compose(doOnCompleteCount(i -> runOnFx(i,onComplete)));
}
/**
* Performs an action on FX thread on onError with the provided emission count
* @param onError
* @param
*/
public static ObservableTransformer doOnErrorCountFx(Consumer onError) {
return obs -> obs.compose(doOnErrorCount(i -> runOnFx(i,onError)));
}
private static class OperatorEmissionCounter implements ObservableOperator {
private final CountObserver ctObserver;
OperatorEmissionCounter(CountObserver ctObserver) {
this.ctObserver = ctObserver;
}
@Override
public Observer super T> apply(Observer super T> child) {
return new ResourceObserver() {
private int count = 0;
private boolean done = false;
@Override
public void onComplete() {
if (done)
return;
try {
if (ctObserver.doOnCompletedCountAction != null)
ctObserver.doOnCompletedCountAction.accept(count);
} catch (Exception e) {
Exceptions.throwIfFatal(e);
onError(e);
return;
}
done = true;
child.onComplete();
}
@Override
public void onError(Throwable e) {
if (done)
return;
try {
if (ctObserver.doOnErrorCountAction != null)
ctObserver.doOnErrorCountAction.accept(count);
} catch(Exception e1) {
Exceptions.throwIfFatal(e1);
child.onError(e1);
}
}
@Override
public void onNext(T t) {
if (done)
return;
try {
if (ctObserver.doOnNextCountAction != null)
ctObserver.doOnNextCountAction.accept(++count);
} catch(Exception e) {
Exceptions.throwIfFatal(e);
onError(e);
return;
}
child.onNext(t);
}
};
}
}
private static final class CountObserver {
private final Consumer doOnNextCountAction;
private final Consumer doOnCompletedCountAction;
private final Consumer doOnErrorCountAction;
CountObserver(Consumer doOnNextCountAction, Consumer doOnCompletedCountAction, Consumer doOnErrorCountAction) {
this.doOnNextCountAction = doOnNextCountAction;
this.doOnCompletedCountAction = doOnCompletedCountAction;
this.doOnErrorCountAction = doOnErrorCountAction;
}
}
}