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

org.reactfx.SuspendableBase Maven / Gradle / Ivy

There is a newer version: 1.11
Show newest version
package org.reactfx;

import org.reactfx.util.AccumulationFacility;
import org.reactfx.util.AccumulatorSize;
import org.reactfx.util.NotificationAccumulator;

public abstract class SuspendableBase
extends ObservableBase
implements Suspendable {
    private final EventStream input;
    private final AccumulationFacility af;

    private int suspended = 0;
    private boolean hasValue = false;
    private A accumulatedValue = null;

    protected SuspendableBase(
            EventStream input,
            NotificationAccumulator pn) {
        super(pn);
        this.input = input;
        this.af = pn.getAccumulationFacility();
    }

    protected abstract AccumulatorSize sizeOf(A accum);
    protected abstract T headOf(A accum);
    protected abstract A tailOf(A accum);

    protected A initialAccumulator(T value) {
        return af.initialAccumulator(value);
    }

    protected A reduce(A accum, T value) {
        return af.reduce(accum, value);
    }

    protected final boolean isSuspended() {
        return suspended > 0;
    }

    @Override
    public final Guard suspend() {
        ++suspended;
        return Guard.closeableOnce(this::resume);
    }

    @Override
    protected final Subscription observeInputs() {
        Subscription sub = input.subscribe(this::handleEvent);
        return sub.and(this::reset);
    }

    private void resume() {
        --suspended;
        if(suspended == 0 && hasValue) {
            while(sizeOf(accumulatedValue) == AccumulatorSize.MANY) {
                enqueueNotifications(headOf(accumulatedValue));
                accumulatedValue = tailOf(accumulatedValue);
            }
            if(sizeOf(accumulatedValue) == AccumulatorSize.ONE) {
                enqueueNotifications(headOf(accumulatedValue));
            }
            reset();
            notifyObservers();
        }
    }

    private void reset() {
        hasValue = false;
        accumulatedValue = null;
    }

    private void handleEvent(T event) {
        if(isSuspended()) {
            if(hasValue) {
                accumulatedValue = reduce(accumulatedValue, event);
            } else {
                accumulatedValue = initialAccumulator(event);
                hasValue = true;
            }
        } else {
            notifyObservers(event);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy