Jcasariego has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/350596 )
Change subject: Retrofit GetDescriptionsTask ...................................................................... Retrofit GetDescriptionsTask Port GetDescriptionTask to Retrofit and try to stay as consistent as possible with the existing code. Bug: T152405 Change-Id: I857c8f07a8df09590676629fb5f01bc0e4fcb8c7 --- D app/src/androidTest/java/org/wikipedia/wikidata/GetDescriptionsTaskTest.java M app/src/main/java/org/wikipedia/page/DisambigListAdapter.java A app/src/main/java/org/wikipedia/wikidata/GetDescriptionsClient.java D app/src/main/java/org/wikipedia/wikidata/GetDescriptionsTask.java A app/src/test/java/org/wikipedia/wikidata/GetDescriptionClientTest.java 5 files changed, 199 insertions(+), 116 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia refs/changes/96/350596/1 diff --git a/app/src/androidTest/java/org/wikipedia/wikidata/GetDescriptionsTaskTest.java b/app/src/androidTest/java/org/wikipedia/wikidata/GetDescriptionsTaskTest.java deleted file mode 100644 index 156184a..0000000 --- a/app/src/androidTest/java/org/wikipedia/wikidata/GetDescriptionsTaskTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.wikipedia.wikidata; - - -import org.junit.Test; -import org.wikipedia.WikipediaApp; -import org.wikipedia.dataclient.WikiSite; -import org.wikipedia.page.PageTitle; -import org.wikipedia.testlib.TestLatch; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.wikipedia.test.TestUtil.runOnMainSync; - -/** - * Tests retrieval of Wikidata descriptions through enwiki. - */ -public class GetDescriptionsTaskTest { - private static final WikiSite WIKI = WikiSite.forLanguageCode("en"); - - @Test public void testOneTitle() throws Throwable { - getWikidataDescriptions(new PageTitle[] { - new PageTitle("Test", WIKI)} - ); - } - - @Test public void testThreeTitles() { - getWikidataDescriptions(new PageTitle[] { - new PageTitle("SAT", WIKI), - new PageTitle("Miller–Rabin primality test", WIKI), - new PageTitle("Radiocarbon dating", WIKI) - }); - } - - private void getWikidataDescriptions(final PageTitle[] ids) { - final List<PageTitle> idList = new ArrayList<>(Arrays.asList(ids)); - final TestLatch latch = new TestLatch(); - runOnMainSync(new Runnable() { - @Override - public void run() { - WikipediaApp app = WikipediaApp.getInstance(); - new GetDescriptionsTask(app.getAPIForSite(WIKI), WIKI, idList) { - @Override - public void onFinish(Map<PageTitle, Void> descriptionsMap) { - assertThat(descriptionsMap, notNullValue()); - assertThat(descriptionsMap.size(), is(idList.size())); - for (PageTitle title : idList) { - assertThat(title.getDescription(), notNullValue()); - } - latch.countDown(); - } - }.execute(); - } - }); - latch.await(); - } -} diff --git a/app/src/main/java/org/wikipedia/page/DisambigListAdapter.java b/app/src/main/java/org/wikipedia/page/DisambigListAdapter.java index 420217c..b9a11ca 100644 --- a/app/src/main/java/org/wikipedia/page/DisambigListAdapter.java +++ b/app/src/main/java/org/wikipedia/page/DisambigListAdapter.java @@ -20,7 +20,7 @@ import org.wikipedia.pageimages.PageImagesClient; import org.wikipedia.views.GoneIfEmptyTextView; import org.wikipedia.views.ViewUtil; -import org.wikipedia.wikidata.GetDescriptionsTask; +import org.wikipedia.wikidata.GetDescriptionsClient; import java.util.ArrayList; import java.util.List; @@ -90,16 +90,17 @@ return; } - new GetDescriptionsTask(app.getSiteApi(), wiki, titleList) { - @Override - public void onFinish(Map<PageTitle, Void> result) { + new GetDescriptionsClient().request(wiki, titleList, new GetDescriptionsClient.Callback() { + @Override public void success(@NonNull Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call, + @NonNull Map<PageTitle, Void> results) { notifyDataSetChanged(); } + @Override - public void onCatch(Throwable caught) { + public void failure(@NonNull Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call, @NonNull Throwable caught) { // descriptions are expendable } - }.execute(); + }); } class ViewHolder { diff --git a/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsClient.java b/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsClient.java new file mode 100644 index 0000000..fa85d17 --- /dev/null +++ b/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsClient.java @@ -0,0 +1,96 @@ +package org.wikipedia.wikidata; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; + +import org.wikipedia.dataclient.WikiSite; +import org.wikipedia.dataclient.mwapi.MwException; +import org.wikipedia.dataclient.mwapi.MwQueryPage; +import org.wikipedia.dataclient.mwapi.MwQueryResponse; +import org.wikipedia.dataclient.retrofit.MwCachedService; +import org.wikipedia.page.PageTitle; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * Populates a list of PageTitles with Wikidata descriptions for each item. + * This task doesn't "return" anything; it simply modifies the PageTitle objects in place. + */ +public class GetDescriptionsClient { + @NonNull private MwCachedService<Service> cachedService = new MwCachedService<>(Service.class); + + public interface Callback { + void success(@NonNull Call<MwQueryResponse<QueryResult>> call, @NonNull Map<PageTitle, Void> results); + void failure(@NonNull Call<MwQueryResponse<QueryResult>> call, @NonNull Throwable caught); + } + + public Call<MwQueryResponse<QueryResult>> request(@NonNull WikiSite wiki, + @NonNull List<PageTitle> titles, + @NonNull Callback cb) { + return request(wiki, cachedService.service(wiki), titles, cb); + } + + @VisibleForTesting Call<MwQueryResponse<QueryResult>> request(final WikiSite wiki, @NonNull Service service, + @NonNull final List<PageTitle> titles, + @NonNull final Callback cb) { + Call<MwQueryResponse<QueryResult>> call = service.request(TextUtils.join("|", titles), ""); + + call.enqueue(new retrofit2.Callback<MwQueryResponse<QueryResult>>() { + @Override public void onResponse(Call<MwQueryResponse<QueryResult>> call, + Response<MwQueryResponse<QueryResult>> response) { + Map<PageTitle, Void> map = new ArrayMap<>(); + + if (response.body().success()) { + for (MwQueryPage page : response.body().query().pages()) { + PageTitle pageTitle = new PageTitle(null, page.title(), wiki); + + for (PageTitle title : titles) { + if (title.getPrefixedText().equals(pageTitle.getPrefixedText()) + || title.getDisplayText().equals(pageTitle.getDisplayText())) { + title.setDescription(page.description()); + break; + } + } + map.put(pageTitle, null); + } + cb.success(call, map); + } else if (response.body().hasError()) { + cb.failure(call, new MwException(response.body().getError())); + } else { + cb.failure(call, new IOException("An unknown error occurred.")); + } + } + + @Override + public void onFailure(Call<MwQueryResponse<QueryResult>> call, Throwable t) { + cb.failure(call, t); + } + }); + + return call; + } + + public class QueryResult { + @SuppressWarnings("unused") @Nullable private List<MwQueryPage> pages; + @Nullable List<MwQueryPage> pages() { + return pages; + } + } + + @VisibleForTesting interface Service { + @GET("w/api.php?action=query&format=json&formatversion=2&prop=pageterms&wbptterm=description") + Call<MwQueryResponse<QueryResult>> request(@NonNull @Query("titles") String titles, + @Query("continue") String continues); + + } +} diff --git a/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsTask.java b/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsTask.java deleted file mode 100644 index 2012f26..0000000 --- a/app/src/main/java/org/wikipedia/wikidata/GetDescriptionsTask.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.wikipedia.wikidata; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.mediawiki.api.json.Api; -import org.mediawiki.api.json.RequestBuilder; -import org.wikipedia.dataclient.WikiSite; -import org.wikipedia.page.PageQueryTask; -import org.wikipedia.page.PageTitle; - -import java.util.List; - -/** - * Populates a list of PageTitles with Wikidata descriptions for each item. - * This task doesn't "return" anything; it simply modifies the PageTitle objects in place. - */ -public class GetDescriptionsTask extends PageQueryTask<Void> { - private List<PageTitle> titles; - - public GetDescriptionsTask(Api api, WikiSite wiki, List<PageTitle> titles) { - super(api, wiki, titles); - this.titles = titles; - } - - @Override - public void buildQueryParams(RequestBuilder builder) { - builder.param("prop", "pageterms") - .param("wbptterm", "description"); - } - - @Override - public Void processPage(int pageId, PageTitle pageTitle, JSONObject pageData) throws Throwable { - JSONObject terms = pageData.optJSONObject("terms"); - if (terms != null) { - final JSONArray array = terms.optJSONArray("description"); - if (array != null && array.length() > 0) { - for (PageTitle title : titles) { - if (title.getPrefixedText().equals(pageTitle.getPrefixedText()) - || title.getDisplayText().equals(pageTitle.getDisplayText())) { - title.setDescription(array.getString(0)); - break; - } - } - } - } - return null; - } -} diff --git a/app/src/test/java/org/wikipedia/wikidata/GetDescriptionClientTest.java b/app/src/test/java/org/wikipedia/wikidata/GetDescriptionClientTest.java new file mode 100644 index 0000000..cf43b7b --- /dev/null +++ b/app/src/test/java/org/wikipedia/wikidata/GetDescriptionClientTest.java @@ -0,0 +1,96 @@ +package org.wikipedia.wikidata; + +import android.support.annotation.NonNull; + +import com.google.gson.stream.MalformedJsonException; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.wikipedia.dataclient.WikiSite; +import org.wikipedia.dataclient.mwapi.MwException; +import org.wikipedia.dataclient.mwapi.MwQueryResponse; +import org.wikipedia.dataclient.okhttp.HttpStatusException; +import org.wikipedia.page.PageTitle; +import org.wikipedia.test.MockWebServerTest; + +import java.util.Arrays; +import java.util.Map; + +import retrofit2.Call; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class GetDescriptionClientTest extends MockWebServerTest { + private static final WikiSite WIKISITE_TEST = WikiSite.forLanguageCode("test"); + private static final PageTitle PAGE_TITLE_BIDEN = new PageTitle("Joe Biden", WIKISITE_TEST); + private static final PageTitle PAGE_TITLE_OBAMA = new PageTitle("Barack Obama", WIKISITE_TEST); + + @NonNull private final GetDescriptionsClient subject = new GetDescriptionsClient(); + + @Test public void testRequestSuccess() throws Throwable { + enqueueFromFile("reading_list_page_info.json"); + + GetDescriptionsClient.Callback cb = mock(GetDescriptionsClient.Callback.class); + Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call = request(cb); + + server().takeRequest(); + + ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class); + verify(cb).success(eq(call), captor.capture()); + + assertThat(PAGE_TITLE_BIDEN.getDescription(), is("47th Vice President of the United States")); + assertThat(PAGE_TITLE_OBAMA.getDescription(), is("44th President of the United States of America")); + + } + + @Test public void testRequestResponseApiError() throws Throwable { + enqueueFromFile("api_error.json"); + + GetDescriptionsClient.Callback cb = mock(GetDescriptionsClient.Callback.class); + Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call = request(cb); + + server().takeRequest(); + assertCallbackFailure(call, cb, MwException.class); + } + + @Test public void testRequestResponseFailure() throws Throwable { + enqueue404(); + + GetDescriptionsClient.Callback cb = mock(GetDescriptionsClient.Callback.class); + Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call = request(cb); + + server().takeRequest(); + assertCallbackFailure(call, cb, HttpStatusException.class); + } + + @Test public void testRequestResponseMalformed() throws Throwable { + server().enqueue("'"); + + GetDescriptionsClient.Callback cb = mock(GetDescriptionsClient.Callback.class); + Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call = request(cb); + + server().takeRequest(); + assertCallbackFailure(call, cb, MalformedJsonException.class); + } + + private void assertCallbackFailure(@NonNull Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> call, + @NonNull GetDescriptionsClient.Callback cb, + @NonNull Class<? extends Throwable> throwable) { + //noinspection unchecked + verify(cb, never()).success(any(Call.class), any(Map.class)); + verify(cb).failure(eq(call), isA(throwable)); + } + + private Call<MwQueryResponse<GetDescriptionsClient.QueryResult>> request( + @NonNull GetDescriptionsClient.Callback cb) { + return subject.request(WIKISITE_TEST, service(GetDescriptionsClient.Service.class), + Arrays.asList(PAGE_TITLE_BIDEN, PAGE_TITLE_OBAMA), cb); + } +} -- To view, visit https://gerrit.wikimedia.org/r/350596 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I857c8f07a8df09590676629fb5f01bc0e4fcb8c7 Gerrit-PatchSet: 1 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Jcasariego <jorgek...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits