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

hu.akarnokd.rxjava2.interop.ObservableCollector 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.function.*;
import java.util.stream.Collector;

import io.reactivex.*;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.internal.disposables.*;
import io.reactivex.internal.observers.DeferredScalarDisposable;
import io.reactivex.plugins.RxJavaPlugins;

/**
 * Collect elements of the upstream with the help of the Collector's callback functions.
 *
 * @param  the upstream value type
 * @param  the accumulated type
 * @param  the result type
 */
final class ObservableCollector extends Observable {

    final ObservableSource source;

    final Collector collector;

    ObservableCollector(ObservableSource source, Collector collector) {
        this.source = source;
        this.collector = collector;
    }

    @Override
    protected void subscribeActual(Observer s) {
        A initialValue;
        BiConsumer accumulator;
        Function finisher;

        try {
            initialValue = collector.supplier().get();

            accumulator = collector.accumulator();

            finisher = collector.finisher();
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            EmptyDisposable.error(ex, s);
            return;
        }

        source.subscribe(new CollectorObserver<>(s, initialValue, accumulator, finisher));
    }

    static final class CollectorObserver extends DeferredScalarDisposable
    implements Observer {

        private static final long serialVersionUID = 2129956429647866524L;

        final BiConsumer accumulator;

        final Function finisher;

        A intermediate;

        Disposable d;

        boolean done;

        public CollectorObserver(Observer actual,
                A initialValue, BiConsumer accumulator, Function finisher) {
            super(actual);
            this.intermediate = initialValue;
            this.accumulator = accumulator;
            this.finisher = finisher;
        }

        @Override
        public void onSubscribe(Disposable d) {
            if (DisposableHelper.validate(this.d, d)) {
                this.d = d;

                actual.onSubscribe(this);
            }
        }

        @Override
        public void onNext(T t) {
            if (!done) {
                try {
                    accumulator.accept(intermediate, t);
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    d.dispose();
                    onError(ex);
                }
            }
        }

        @Override
        public void onError(Throwable t) {
            if (done) {
                RxJavaPlugins.onError(t);
            } else {
                done = true;
                intermediate = null;
                actual.onError(t);
            }
        }

        @Override
        public void onComplete() {
            if (!done) {
                R r;

                try {
                    r = finisher.apply(intermediate);
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    onError(ex);
                    return;
                }

                intermediate = null;
                complete(r);
            }
        }

        @Override
        public void dispose() {
            super.dispose();
            d.dispose();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy