package com.novoda.event; import com.jakewharton.rxrelay.BehaviorRelay; import rx.Notification; import rx.Observable; import rx.functions.Func1; import rx.functions.Func2; public final class EventFunctions { private EventFunctions() { throw new IllegalStateException("NonInstantiableClassException"); } public static <T> boolean isInitialised(BehaviorRelay<Event<T>> subject) { return hasData(subject) || isLoading(subject); } private static <T> boolean hasData(BehaviorRelay<Event<T>> subject) { return subject.getValue().data().isPresent(); } private static <T> boolean isLoading(BehaviorRelay<Event<T>> subject) { return subject.getValue().state() == Status.LOADING; } public static <T> Observable.Transformer<T, Event<T>> asEvent(Class<T> clazz) { return asEvent(); } public static <T> Observable.Transformer<T, Event<T>> asEvent() { return asEvent(Event.<T>loading()); } public static <T> Observable.Transformer<T, Event<T>> asEvent(final Event<T> currentEvent) { return new Observable.Transformer<T, Event<T>>() { @Override public Observable<Event<T>> call(Observable<T> observable) { return observable.materialize().compose(EventFunctions.<T>notificationToEvent(currentEvent.asLoading())); } }; } public static <T> Observable.Transformer<Notification<T>, Event<T>> notificationToEvent(final Event<T> startWith) { return new Observable.Transformer<Notification<T>, Event<T>>() { @Override public Observable<Event<T>> call(Observable<Notification<T>> observable) { return observable .scan( startWith, new Func2<Event<T>, Notification<T>, Event<T>>() { @Override public Event<T> call(Event<T> event, Notification<T> notification) { switch (notification.getKind()) { case OnNext: return event.asLoadingWithData(notification.getValue()); case OnCompleted: return event.asIdle(); case OnError: return event.asError(notification.getThrowable()); default: throw new IllegalStateException("No case defined for kind " + notification.getKind()); } } } ) .startWith(startWith) .distinctUntilChanged(); } }; } public static <T> Observable.Transformer<Event<T>, T> asData(Class<T> clazz) { return asData(); } public static <T> Observable.Transformer<Event<T>, T> asData() { return new Observable.Transformer<Event<T>, T>() { @Override public Observable<T> call(Observable<Event<T>> observable) { return observable .filter(EventFunctions.<T>dataPresent()) .map(EventFunctions.<T>extractData()) .distinctUntilChanged(); } }; } private static <T> Func1<Event<T>, Boolean> dataPresent() { return new Func1<Event<T>, Boolean>() { @Override public Boolean call(Event<T> event) { return event.data().isPresent(); } }; } private static <T> Func1<Event<T>, T> extractData() { return new Func1<Event<T>, T>() { @Override public T call(Event<T> event) { return event.data().get(); } }; } }