package com.simplecity.amp_library.sql.sqlbrite; import android.database.Cursor; import com.squareup.sqlbrite.SqlBrite; import rx.Observable; import rx.Subscriber; import rx.exceptions.Exceptions; import rx.exceptions.OnErrorThrowable; import rx.functions.Func1; final class QueryToOneOperator<T> implements Observable.Operator<T, SqlBrite.Query> { final Func1<Cursor, T> mapper; boolean emitDefault; T defaultValue; QueryToOneOperator(Func1<Cursor, T> mapper, boolean emitDefault, T defaultValue) { this.mapper = mapper; this.emitDefault = emitDefault; this.defaultValue = defaultValue; } @Override public Subscriber<? super SqlBrite.Query> call(final Subscriber<? super T> subscriber) { return new Subscriber<SqlBrite.Query>(subscriber) { @Override public void onNext(SqlBrite.Query query) { try { boolean emit = false; T item = null; Cursor cursor = query.run(); if (cursor != null) { try { if (cursor.moveToNext()) { item = mapper.call(cursor); emit = true; if (cursor.moveToNext()) { throw new IllegalStateException("Cursor returned more than 1 row"); } } } finally { cursor.close(); } } if (!subscriber.isUnsubscribed()) { if (emit) { subscriber.onNext(item); } else if (emitDefault) { subscriber.onNext(defaultValue); } else { request(1L); // Account upstream for the lack of downstream emission. } } } catch (Throwable e) { Exceptions.throwIfFatal(e); onError(OnErrorThrowable.addValueAsLastCause(e, query.toString())); } } @Override public void onCompleted() { subscriber.onCompleted(); } @Override public void onError(Throwable e) { subscriber.onError(e); } }; } }