package com.github.davidmoten.rx;
import com.github.davidmoten.rx.util.BackpressureStrategy;
import rx.Observable.Transformer;
import rx.Subscriber;
import rx.functions.Func0;
import rx.functions.Func2;
import rx.functions.Func3;
public final class StateMachine {
private StateMachine() {
// prevent instantiation
}
public static interface Transition<State, In, Out>
extends Func3<State, In, Subscriber<Out>, State> {
// override so IDEs have better suggestions for parameters
@Override
public State call(State state, In value, Subscriber<Out> subscriber);
}
public static interface Completion<State, Out> extends Func2<State, Subscriber<Out>, Boolean> {
// override so IDEs have better suggestions for parameters
@Override
public Boolean call(State state, Subscriber<Out> subscriber);
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private Builder() {
// prevent instantiation from other packages
}
public <State> Builder2<State> initialStateFactory(Func0<State> initialState) {
return new Builder2<State>(initialState);
}
public <State> Builder2<State> initialState(final State initialState) {
return new Builder2<State>(Functions.constant0(initialState));
}
}
public static final class Builder2<State> {
private final Func0<State> initialState;
private Builder2(Func0<State> initialState) {
this.initialState = initialState;
}
public <In, Out> Builder3<State, In, Out> transition(
Transition<State, In, Out> transition) {
return new Builder3<State, In, Out>(initialState, transition);
}
}
public static final class Builder3<State, In, Out> {
private final Func0<State> initialState;
private final Transition<State, In, Out> transition;
private Completion<State, Out> completion = CompletionAlwaysTrueHolder.instance();
private BackpressureStrategy backpressureStrategy = BackpressureStrategy.BUFFER;
private int initialRequest = Transformers.DEFAULT_INITIAL_BATCH;
private Builder3(Func0<State> initialState, Transition<State, In, Out> transition) {
this.initialState = initialState;
this.transition = transition;
}
public Builder3<State, In, Out> completion(Completion<State, Out> completion) {
this.completion = completion;
return this;
}
public Builder3<State, In, Out> backpressureStrategy(
BackpressureStrategy backpressureStrategy) {
this.backpressureStrategy = backpressureStrategy;
return this;
}
public Builder3<State, In, Out> initialRequest(int value) {
this.initialRequest = value;
return this;
}
public Transformer<In, Out> build() {
return Transformers.stateMachine(initialState, transition, completion,
backpressureStrategy, initialRequest);
}
}
private static final class CompletionAlwaysTrueHolder {
private static final Completion<Object, Object> INSTANCE = new Completion<Object, Object>() {
@Override
public Boolean call(Object t1, Subscriber<Object> t2) {
return true;
}
};
@SuppressWarnings("unchecked")
static <State, Out> Completion<State, Out> instance() {
return (Completion<State, Out>) INSTANCE;
}
}
}