/**
* Copyright 2009-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 net.javacrumbs.futureconverter.rxjavacommon;
import net.javacrumbs.futureconverter.common.internal.ValueSource;
import rx.Single;
import rx.Subscription;
import rx.subscriptions.Subscriptions;
import java.util.function.Consumer;
public class RxJavaFutureUtils {
public static <T> Single<T> createSingle(ValueSource<T> valueSource) {
if (valueSource instanceof SingleBackedValueSource) {
return ((SingleBackedValueSource<T>) valueSource).getSingle();
}
return new ValueSourceBackedSingle<>(valueSource);
}
public static <T> ValueSource<T> createValueSource(Single<T> single) {
if (single instanceof ValueSourceBackedSingle) {
return ((ValueSourceBackedSingle<T>) single).getValueSource();
} else {
return new SingleBackedValueSource<>(single);
}
}
private static class SingleBackedValueSource<T> implements ValueSource<T> {
private final Single<T> single;
private Subscription subscription;
private SingleBackedValueSource(Single<T> single) {
this.single = single;
}
@Override
public void addCallbacks(Consumer<T> successCallback, Consumer<Throwable> failureCallback) {
if (subscription == null) {
subscription = single.subscribe(successCallback::accept, failureCallback::accept);
} else {
throw new IllegalStateException("add callbacks can be called only once");
}
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
subscription.unsubscribe();
return true;
}
private Single<T> getSingle() {
return single;
}
}
private static class ValueSourceBackedSingle<T> extends Single<T> {
private final ValueSource<T> valueSource;
ValueSourceBackedSingle(ValueSource<T> valueSource) {
super(onSubscribe(valueSource));
this.valueSource = valueSource;
}
private static <T> OnSubscribe<T> onSubscribe(final ValueSource<T> valueSource) {
return subscriber -> {
valueSource.addCallbacks(value -> {
if (!subscriber.isUnsubscribed()) {
try {
subscriber.onSuccess(value);
} catch (Throwable e) {
subscriber.onError(e);
}
}
},
throwable -> {
if (!subscriber.isUnsubscribed()) {
subscriber.onError(throwable);
}
});
subscriber.add(Subscriptions.create(() -> valueSource.cancel(true)));
};
}
private ValueSource<T> getValueSource() {
return valueSource;
}
}
}