Mholloway has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/365427 )
Change subject: Add offline compilation client ...................................................................... Add offline compilation client Bug: T163714 Change-Id: I2b11abad2e62293a8a59b7b50b90c836a6ca961e --- A app/src/main/java/org/wikipedia/offline/CompilationClient.java A app/src/main/java/org/wikipedia/offline/CompilationInfo.java A app/src/test/java/org/wikipedia/offline/CompilationClientTest.java 3 files changed, 230 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia refs/changes/27/365427/1 diff --git a/app/src/main/java/org/wikipedia/offline/CompilationClient.java b/app/src/main/java/org/wikipedia/offline/CompilationClient.java new file mode 100644 index 0000000..1d1a06c --- /dev/null +++ b/app/src/main/java/org/wikipedia/offline/CompilationClient.java @@ -0,0 +1,104 @@ +package org.wikipedia.offline; + + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; + +import org.wikipedia.dataclient.WikiSite; +import org.wikipedia.dataclient.retrofit.RetrofitFactory; +import org.wikipedia.json.annotations.Required; +import org.wikipedia.settings.Prefs; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; + +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.http.GET; +import retrofit2.http.Headers; + +import static org.wikipedia.Constants.ACCEPT_HEADER_PREFIX; + +class CompilationClient { + interface Callback { + void success(@NonNull List<CompilationInfo> compilations); + void error(@NonNull Throwable caught); + } + + @Nullable private Call<CallbackAdapter.CompilationResponse> call; + + // todo: according to Jake Wharton, Retrofit service objects are very expensive and should only + // be created once for the application and then cached for reuse. Figure out how to make these + // WikiSite-independent, and create once. + // https://stackoverflow.com/a/20627010/5520737 + public void request(@NonNull WikiSite wiki, @NonNull Callback cb) { + cancel(); + Retrofit retrofit = RetrofitFactory.newInstance(getEndpoint(wiki), wiki); + Service service = retrofit.create(Service.class); + call = request(service); + call.enqueue(new CallbackAdapter(cb)); + } + + public void cancel() { + if (call == null) { + return; + } + call.cancel(); + call = null; + } + + @VisibleForTesting @NonNull + Call<CallbackAdapter.CompilationResponse> request(@NonNull Service service) { + return service.get(); + } + + @VisibleForTesting + static class CallbackAdapter implements retrofit2.Callback<CallbackAdapter.CompilationResponse> { + private Callback cb; + + CallbackAdapter(Callback cb) { + this.cb = cb; + } + + @Override + public void onResponse(@NonNull Call<CompilationResponse> call, + @NonNull Response<CompilationResponse> response) { + // noinspection ConstantConditions + if (response.body() != null && response.body().compilations() != null) { + // noinspection ConstantConditions + cb.success(response.body().compilations()); + } else { + cb.error(new IOException("An unknown error occurred.")); + } + } + + @Override + public void onFailure(@NonNull Call<CompilationResponse> call, @NonNull Throwable t) { + cb.error(t); + } + + static class CompilationResponse { + @SuppressWarnings("unused,NullableProblems") @NonNull @Required + private List<CompilationInfo> compilations; + + @Nullable + List<CompilationInfo> compilations() { + return compilations; + } + } + } + + // todo: update endpoint path when finalized + @VisibleForTesting + interface Service { + @NonNull @Headers(ACCEPT_HEADER_PREFIX + "compilations/0.1.0\"") @GET("/compilations") + Call<CallbackAdapter.CompilationResponse> get(); + } + + private String getEndpoint(WikiSite wiki) { + return String.format(Locale.ROOT, Prefs.getRestbaseUriFormat(), wiki.scheme(), wiki.authority()); + } +} diff --git a/app/src/main/java/org/wikipedia/offline/CompilationInfo.java b/app/src/main/java/org/wikipedia/offline/CompilationInfo.java new file mode 100644 index 0000000..386dcab --- /dev/null +++ b/app/src/main/java/org/wikipedia/offline/CompilationInfo.java @@ -0,0 +1,59 @@ +package org.wikipedia.offline; + + +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.gson.annotations.SerializedName; + +import java.util.Date; + +// A Gson POJO that will model the compilations endpoint response. TODO: Finalize when the spec is defined. +class CompilationInfo { + @SuppressWarnings("unused,NullableProblems") @NonNull private String filename; + @SuppressWarnings("unused,NullableProblems") @NonNull private String summary; + @SuppressWarnings("unused,NullableProblems") @NonNull private String description; + @SuppressWarnings("unused,NullableProblems") @SerializedName("thumb_url") @NonNull private Uri thumbUrl; + @SuppressWarnings("unused,NullableProblems") @SerializedName("image_url") @NonNull private Uri imageUrl; // full-size image + @SuppressWarnings("unused") @SerializedName("article_count") private int articleCount; + @SuppressWarnings("unused") private long size; // bytes + @SuppressWarnings("unused") private long timestamp; + + @NonNull + public String getFilename() { + return filename; + } + + @NonNull + public String getSummary() { + return summary; + } + + @NonNull + public String getDescription() { + return description; + } + + @NonNull + public Uri getThumbUrl() { + return thumbUrl; + } + + @NonNull + public Uri getImageUrl() { + return imageUrl; + } + + public int getArticleCount() { + return articleCount; + } + + public long getSize() { + return size; + } + + @NonNull + public Date getDate() { + return new Date(timestamp); + } +} diff --git a/app/src/test/java/org/wikipedia/offline/CompilationClientTest.java b/app/src/test/java/org/wikipedia/offline/CompilationClientTest.java new file mode 100644 index 0000000..38d23b2 --- /dev/null +++ b/app/src/test/java/org/wikipedia/offline/CompilationClientTest.java @@ -0,0 +1,67 @@ +package org.wikipedia.offline; + +import android.support.annotation.NonNull; + +import org.junit.Test; +import org.wikipedia.offline.CompilationClient.Callback; +import org.wikipedia.test.MockWebServerTest; + +import retrofit2.Call; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class CompilationClientTest extends MockWebServerTest { + @NonNull private CompilationClient subject = new CompilationClient(); + + // todo: update when compilation info spec is finalized + @Test + public void testRequestSuccess() throws Throwable { + server().enqueue("{ \"compilations\": [] }"); + Callback cb = mock(Callback.class); + request(cb); + server().takeRequest(); + verify(cb).success(anyListOf(CompilationInfo.class)); + //noinspection unchecked + verify(cb, never()).error(any(Throwable.class)); + } + + @Test + public void testRequestMalformed() throws Throwable { + server().enqueue("ææææææææææææææææææ"); + Callback cb = mock(Callback.class); + request(cb); + server().takeRequest(); + verify(cb, never()).success(anyListOf(CompilationInfo.class)); + verify(cb).error(any(Throwable.class)); + } + + @Test + public void testRequestEmpty() throws Throwable { + enqueueEmptyJson(); + Callback cb = mock(Callback.class); + request(cb); + server().takeRequest(); + verify(cb, never()).success(anyListOf(CompilationInfo.class)); + verify(cb).error(any(Throwable.class)); + } + + @Test + public void testRequestNotFound() throws Throwable { + enqueue404(); + Callback cb = mock(Callback.class); + request(cb); + server().takeRequest(); + verify(cb, never()).success(anyListOf(CompilationInfo.class)); + verify(cb).error(any(Throwable.class)); + } + + private void request(@NonNull CompilationClient.Callback cb) { + Call<CompilationClient.CallbackAdapter.CompilationResponse> call + = subject.request(service(CompilationClient.Service.class)); + call.enqueue(new CompilationClient.CallbackAdapter(cb)); + } +} -- To view, visit https://gerrit.wikimedia.org/r/365427 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2b11abad2e62293a8a59b7b50b90c836a6ca961e Gerrit-PatchSet: 1 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Mholloway <mhollo...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits