Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support io.reactivex.Maybe #857

Merged
merged 3 commits into from
Nov 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import io.reactivex.Completable;

/**
* Common API of prepared write operations
* Common API of prepared operations with {@link Completable} support
*
* @param <Result> type of result
*/
public interface PreparedWriteOperation<Result, Data> extends PreparedOperation<Result, Result, Data> {
public interface PreparedCompletableOperation<Result, Data> extends PreparedOperation<Result, Result, Data> {

@NonNull
@CheckResult
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.pushtorefresh.storio2.operations;

import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import io.reactivex.Maybe;

/**
* Common API of prepared operations with {@link Maybe} support
*
* @param <Result> type of result
*/
public interface PreparedMaybeOperation<Result, WrappedResult, Data> extends PreparedOperation<Result, WrappedResult, Data> {

@NonNull
@CheckResult
Maybe<Result> asRxMaybe();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.pushtorefresh.storio2.operations.internal;

import android.support.annotation.NonNull;
import com.pushtorefresh.storio2.operations.PreparedMaybeOperation;
import io.reactivex.MaybeEmitter;
import io.reactivex.MaybeOnSubscribe;

/**
* Required to avoid problems with ClassLoader when RxJava is not in ClassPath
* We can not use anonymous classes from RxJava directly in StorIO, ClassLoader won't be happy :(
* <p>
* For internal usage only!
*/
public final class MaybeOnSubscribeExecuteAsBlocking<Result, WrappedResult, Data> implements MaybeOnSubscribe<Result> {

@NonNull
private final PreparedMaybeOperation<Result, WrappedResult, Data> preparedOperation;

public MaybeOnSubscribeExecuteAsBlocking(@NonNull PreparedMaybeOperation<Result, WrappedResult, Data> preparedOperation) {
this.preparedOperation = preparedOperation;
}

@Override
public void subscribe(MaybeEmitter<Result> emitter) throws Exception {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nullability

try {
final Result value = preparedOperation.executeAsBlocking();
if (value != null) {
emitter.onSuccess(value);
} else {
emitter.onComplete();
}
} catch (Exception e) {
emitter.onError(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.pushtorefresh.storio2.operations.internal;

import com.pushtorefresh.storio2.StorIOException;
import com.pushtorefresh.storio2.operations.PreparedWriteOperation;
import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;

import org.junit.Test;

Expand All @@ -21,7 +21,7 @@ public class CompletableOnSubscribeExecuteAsBlockingTest {
@SuppressWarnings("ResourceType")
@Test
public void shouldExecuteAsBlockingAfterSubscription() {
final PreparedWriteOperation preparedOperation = mock(PreparedWriteOperation.class);
final PreparedCompletableOperation preparedOperation = mock(PreparedCompletableOperation.class);

TestObserver testObserver = new TestObserver();

Expand All @@ -45,7 +45,7 @@ public void shouldExecuteAsBlockingAfterSubscription() {
@SuppressWarnings({"ThrowableInstanceNeverThrown", "ResourceType"})
@Test
public void shouldCallOnErrorIfExceptionOccurred() {
final PreparedWriteOperation preparedOperation = mock(PreparedWriteOperation.class);
final PreparedCompletableOperation preparedOperation = mock(PreparedCompletableOperation.class);

StorIOException expectedException = new StorIOException("test exception");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.pushtorefresh.storio2.operations.internal;

import com.pushtorefresh.storio2.StorIOException;
import com.pushtorefresh.storio2.operations.PreparedMaybeOperation;

import org.junit.Test;

import io.reactivex.Maybe;
import io.reactivex.observers.TestObserver;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

public class MaybeOnSubscribeExecuteAsBlockingTest {

@SuppressWarnings("CheckResult")
@Test
public void shouldExecuteAsBlockingAfterSubscription() {
//noinspection unchecked
final PreparedMaybeOperation<String, String, String> preparedOperation = mock(PreparedMaybeOperation.class);
String expectedResult = "test";
when(preparedOperation.executeAsBlocking()).thenReturn(expectedResult);

TestObserver<String> testObserver = new TestObserver<String>();

verifyZeroInteractions(preparedOperation);

Maybe<String> maybe = Maybe.create(new MaybeOnSubscribeExecuteAsBlocking<String, String, String>(preparedOperation));

verifyZeroInteractions(preparedOperation);

maybe.subscribe(testObserver);

testObserver.assertValue(expectedResult);
testObserver.assertNoErrors();
testObserver.assertComplete();

verify(preparedOperation).executeAsBlocking();
}

@SuppressWarnings("CheckResult")
@Test
public void shouldCompleteIfNullOccurred() {
//noinspection unchecked
final PreparedMaybeOperation<String, String, String> preparedOperation = mock(PreparedMaybeOperation.class);
when(preparedOperation.executeAsBlocking()).thenReturn(null);

TestObserver<String> testObserver = new TestObserver<String>();

verifyZeroInteractions(preparedOperation);

Maybe<String> maybe = Maybe.create(new MaybeOnSubscribeExecuteAsBlocking<String, String, String>(preparedOperation));

verifyZeroInteractions(preparedOperation);

maybe.subscribe(testObserver);

testObserver.assertNoErrors();
testObserver.assertComplete();

verify(preparedOperation).executeAsBlocking();
}

@SuppressWarnings("CheckResult")
@Test
public void shouldCallOnErrorIfExceptionOccurred() {
//noinspection unchecked
final PreparedMaybeOperation<Object, Object, Object> preparedOperation = mock(PreparedMaybeOperation.class);

StorIOException expectedException = new StorIOException("test exception");

when(preparedOperation.executeAsBlocking()).thenThrow(expectedException);

TestObserver<Object> testObserver = new TestObserver<Object>();

Maybe<Object> maybe = Maybe.create(new MaybeOnSubscribeExecuteAsBlocking<Object, Object, Object>(preparedOperation));

verifyZeroInteractions(preparedOperation);

maybe.subscribe(testObserver);

testObserver.assertError(expectedException);
testObserver.assertNotComplete();

verify(preparedOperation).executeAsBlocking();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.pushtorefresh.storio2.contentresolver.queries.Query;
import com.pushtorefresh.storio2.contentresolver.queries.UpdateQuery;

import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;
import java.util.Collections;
import java.util.Set;

Expand Down Expand Up @@ -97,7 +98,7 @@ public Flowable<Changes> observeChangesOfUri(@NonNull Uri uri, @NonNull Backpres
* @return the scheduler or {@code null} if it isn't needed to apply it.
* @see com.pushtorefresh.storio2.operations.PreparedOperation#asRxFlowable(BackpressureStrategy)
* @see com.pushtorefresh.storio2.operations.PreparedOperation#asRxSingle()
* @see com.pushtorefresh.storio2.operations.PreparedWriteOperation#asRxCompletable()
* @see PreparedCompletableOperation#asRxCompletable()
*/
@Nullable
public abstract Scheduler defaultRxScheduler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.pushtorefresh.storio2.contentresolver.queries.UpdateQuery;
import com.pushtorefresh.storio2.internal.TypeMappingFinderImpl;

import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -210,7 +211,7 @@ public CompleteBuilder typeMappingFinder(@NonNull TypeMappingFinder typeMappingF
* <p/>
* @see com.pushtorefresh.storio2.operations.PreparedOperation#asRxFlowable(BackpressureStrategy)
* @see com.pushtorefresh.storio2.operations.PreparedOperation#asRxSingle()
* @see com.pushtorefresh.storio2.operations.PreparedWriteOperation#asRxCompletable()
* @see PreparedCompletableOperation#asRxCompletable()
*
* @return the scheduler or {@code null} if it isn't needed to apply it.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import com.pushtorefresh.storio2.contentresolver.StorIOContentResolver;
import com.pushtorefresh.storio2.contentresolver.queries.DeleteQuery;
import com.pushtorefresh.storio2.operations.PreparedWriteOperation;
import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;

import java.util.Collection;

Expand All @@ -15,7 +15,8 @@
*
* @param <Result> type of result of Delete Operation.
*/
public abstract class PreparedDelete<Result, Data> implements PreparedWriteOperation<Result, Data> {
public abstract class PreparedDelete<Result, Data> implements
PreparedCompletableOperation<Result, Data> {

@NonNull
protected final StorIOContentResolver storIOContentResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import com.pushtorefresh.storio2.contentresolver.StorIOContentResolver;
import com.pushtorefresh.storio2.contentresolver.operations.internal.RxJavaUtils;
import com.pushtorefresh.storio2.contentresolver.queries.Query;
import com.pushtorefresh.storio2.operations.PreparedMaybeOperation;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;

import static com.pushtorefresh.storio2.internal.Checks.checkNotNull;
Expand All @@ -26,7 +28,8 @@
*
* @param <T> type of result.
*/
public class PreparedGetObject<T> extends PreparedGet<T, Optional<T>> {
public class PreparedGetObject<T> extends PreparedGet<T, Optional<T>> implements
PreparedMaybeOperation<T, Optional<T>, Query> {

@NonNull
private final Class<T> type;
Expand Down Expand Up @@ -137,6 +140,12 @@ public Single<Optional<T>> asRxSingle() {
return RxJavaUtils.createSingleOptional(storIOContentResolver, this);
}

@NonNull
@Override
public Maybe<T> asRxMaybe() {
return RxJavaUtils.createMaybe(storIOContentResolver, this);
}

/**
* Builder for {@link PreparedGetObject}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@
import com.pushtorefresh.storio2.contentresolver.Changes;
import com.pushtorefresh.storio2.contentresolver.StorIOContentResolver;
import com.pushtorefresh.storio2.contentresolver.queries.Query;
import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;
import com.pushtorefresh.storio2.operations.PreparedMaybeOperation;
import com.pushtorefresh.storio2.operations.PreparedOperation;
import com.pushtorefresh.storio2.operations.PreparedWriteOperation;
import com.pushtorefresh.storio2.operations.internal.CompletableOnSubscribeExecuteAsBlocking;
import com.pushtorefresh.storio2.operations.internal.FlowableOnSubscribeExecuteAsBlocking;
import com.pushtorefresh.storio2.operations.internal.FlowableOnSubscribeExecuteAsBlockingOptional;
import com.pushtorefresh.storio2.operations.internal.MapSomethingToExecuteAsBlocking;
import com.pushtorefresh.storio2.operations.internal.MapSomethingToExecuteAsBlockingOptional;
import com.pushtorefresh.storio2.operations.internal.MaybeOnSubscribeExecuteAsBlocking;
import com.pushtorefresh.storio2.operations.internal.SingleOnSubscribeExecuteAsBlocking;
import com.pushtorefresh.storio2.operations.internal.SingleOnSubscribeExecuteAsBlockingOptional;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Scheduler;
import io.reactivex.Single;

Expand Down Expand Up @@ -128,7 +131,7 @@ public static <Result, Data> Single<Optional<Result>> createSingleOptional(
@NonNull
public static <Result, Data> Completable createCompletable(
@NonNull StorIOContentResolver storIOContentResolver,
@NonNull PreparedWriteOperation<Result, Data> operation
@NonNull PreparedCompletableOperation<Result, Data> operation
) {
throwExceptionIfRxJava2IsNotAvailable("asRxCompletable()");

Expand All @@ -140,6 +143,20 @@ public static <Result, Data> Completable createCompletable(
);
}

@CheckResult
@NonNull
public static <Result, WrappedResult, Data> Maybe<Result> createMaybe(
@NonNull StorIOContentResolver storIOContentResolver,
@NonNull PreparedMaybeOperation<Result, WrappedResult, Data> operation
) {
throwExceptionIfRxJava2IsNotAvailable("asRxMaybe()");

final Maybe<Result> maybe =
Maybe.create(new MaybeOnSubscribeExecuteAsBlocking<Result, WrappedResult, Data>(operation));

return subscribeOn(storIOContentResolver, maybe);
}

@CheckResult
@NonNull
public static <T> Flowable<T> subscribeOn(
Expand Down Expand Up @@ -169,4 +186,14 @@ public static Completable subscribeOn(
final Scheduler scheduler = storIOContentResolver.defaultRxScheduler();
return scheduler != null ? completable.subscribeOn(scheduler) : completable;
}

@CheckResult
@NonNull
public static <T> Maybe<T> subscribeOn(
@NonNull StorIOContentResolver storIOContentResolver,
@NonNull Maybe<T> maybe
) {
final Scheduler scheduler = storIOContentResolver.defaultRxScheduler();
return scheduler != null ? maybe.subscribeOn(scheduler) : maybe;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import android.support.annotation.NonNull;

import com.pushtorefresh.storio2.contentresolver.StorIOContentResolver;
import com.pushtorefresh.storio2.operations.PreparedWriteOperation;
import com.pushtorefresh.storio2.operations.PreparedCompletableOperation;

import java.util.Collection;

Expand All @@ -13,7 +13,8 @@
* in {@link android.content.ContentProvider}.
*
*/
public abstract class PreparedPut<Result, Data> implements PreparedWriteOperation<Result, Data> {
public abstract class PreparedPut<Result, Data> implements
PreparedCompletableOperation<Result, Data> {

@NonNull
protected final StorIOContentResolver storIOContentResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;

import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -136,4 +137,17 @@ public void getObjectAsSingle() {
.prepare()
.asRxSingle();
}

@Test
public void getObjectAsMaybe() {
Maybe<Article> maybe = storIOContentResolver()
.get()
.object(Article.class)
.withQuery(Query.builder()
.uri(mock(Uri.class))
.build())
.withGetResolver(ArticleMeta.GET_RESOLVER)
.prepare()
.asRxMaybe();
}
}
Loading