package rxfirebase2.database; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.MutableData; import com.google.firebase.database.Query; import com.google.firebase.database.Transaction; import com.google.firebase.database.ValueEventListener; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.Single; import io.reactivex.SingleEmitter; import io.reactivex.SingleOnSubscribe; import io.reactivex.annotations.CheckReturnValue; import io.reactivex.annotations.NonNull; import io.reactivex.annotations.Nullable; import io.reactivex.functions.Cancellable; import io.reactivex.functions.Function; public final class RxValue { /** * @param query * @return */ @NonNull @CheckReturnValue public static Single<DataSnapshot> single(@NonNull final Query query) { return Single.create(new SingleOnSubscribe<DataSnapshot>() { @Override public void subscribe( @NonNull final SingleEmitter<DataSnapshot> emit) throws Exception { final ValueEventListener listener = listener(emit); emit.setCancellable(new Cancellable() { @Override public void cancel() throws Exception { query.removeEventListener(listener); } }); query.addListenerForSingleValueEvent(listener); } }); } /** * @param query * @return */ @NonNull @CheckReturnValue public static Observable<DataSnapshot> changes(@NonNull final Query query) { return Observable.create(new ObservableOnSubscribe<DataSnapshot>() { @Override public void subscribe( @NonNull final ObservableEmitter<DataSnapshot> emit) throws Exception { final ValueEventListener listener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (!emit.isDisposed()) { emit.onNext(dataSnapshot); } } @Override public void onCancelled(DatabaseError e) { if (!emit.isDisposed()) { emit.onError(e.toException()); } } }; emit.setCancellable(new Cancellable() { @Override public void cancel() throws Exception { query.removeEventListener(listener); } }); query.addValueEventListener(listener); } }); } /** * @param emit * @return */ @NonNull @CheckReturnValue public static ValueEventListener listener(@NonNull final SingleEmitter<DataSnapshot> emit) { return new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (!emit.isDisposed()) { emit.onSuccess(dataSnapshot); } } @Override public void onCancelled(DatabaseError e) { if (!emit.isDisposed()) { emit.onError(e.toException()); } } }; } /** * @param ref * @param function * @return */ @NonNull @CheckReturnValue public static Single<DataSnapshot> transaction( @NonNull final DatabaseReference ref, @NonNull final Function<MutableData, Transaction.Result> function) { return Single.create(new SingleOnSubscribe<DataSnapshot>() { @Override public void subscribe( @NonNull final SingleEmitter<DataSnapshot> emit) throws Exception { ref.runTransaction(transaction(emit, function)); } }); } /** * @param ref * @param function * @param fireLocalEvents * @return */ @NonNull @CheckReturnValue public static Single<DataSnapshot> transaction( @NonNull final DatabaseReference ref, @NonNull final Function<MutableData, Transaction.Result> function, final boolean fireLocalEvents) { return Single.create(new SingleOnSubscribe<DataSnapshot>() { @Override public void subscribe( @NonNull final SingleEmitter<DataSnapshot> emit) throws Exception { ref.runTransaction(transaction(emit, function), fireLocalEvents); } }); } //public interface TransactionFunction extends Function<MutableData, Transaction.Result> { //} /** * @param emitter * @param function * @return */ @NonNull @CheckReturnValue public static Transaction.Handler transaction( @NonNull final SingleEmitter<DataSnapshot> emitter, @NonNull final Function<MutableData, Transaction.Result> function) { return new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { try { return function.apply(mutableData); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void onComplete(@Nullable DatabaseError databaseError, boolean committed, @NonNull DataSnapshot dataSnapshot) { if (!emitter.isDisposed()) { if (null == databaseError) { emitter.onSuccess(dataSnapshot); } else { emitter.onError(databaseError.toException()); } } } }; } }