Jcasariego has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/351692 )
Change subject: Retrofit ImageLicenseFetchTask
......................................................................
Retrofit ImageLicenseFetchTask
Port ImageLicenseFetchTask to Retrofit and try to stay as consistent as
possible with the existing code.
Bug T152406
Change-Id: Ib6ad70b969507aaad7356fce2e2e9bf27aaaeddc
---
A app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryImageLicensePage.java
M app/src/main/java/org/wikipedia/gallery/GalleryItem.java
A app/src/main/java/org/wikipedia/page/ImageLicenseFetchClient.java
D app/src/main/java/org/wikipedia/page/ImageLicenseFetchTask.java
M app/src/main/java/org/wikipedia/page/snippet/ShareHandler.java
A app/src/test/java/org/wikipedia/page/ImageLicenseFetchClientTest.java
A app/src/test/res/raw/image_license.json
7 files changed, 403 insertions(+), 73 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia
refs/changes/92/351692/1
diff --git
a/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryImageLicensePage.java
b/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryImageLicensePage.java
new file mode 100644
index 0000000..5a371f6
--- /dev/null
+++
b/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryImageLicensePage.java
@@ -0,0 +1,76 @@
+package org.wikipedia.dataclient.mwapi;
+
+import android.support.annotation.Nullable;
+
+import java.util.List;
+
+public class MwQueryImageLicensePage extends MwQueryPage {
+ @SuppressWarnings("unused") @Nullable private List<ImageInfo> imageinfo;
+
+ public String imageLicense() {
+ return imageinfo != null
+ && imageinfo.get(0).extmetadata() != null
+ && imageinfo.get(0).extmetadata().license() != null
+ ? imageinfo.get(0).extmetadata().license().value() : "";
+ }
+
+ public String imageLicenseShortName() {
+ return imageinfo != null
+ && imageinfo.get(0).extmetadata() != null
+ && imageinfo.get(0).extmetadata().licenseShortName() != null
+ ? imageinfo.get(0).extmetadata().licenseShortName().value() :
"";
+ }
+
+ public String imageLicenseUrl() {
+ return imageinfo != null
+ && imageinfo.get(0).extmetadata() != null
+ && imageinfo.get(0).extmetadata().licenseUrl() != null
+ ? imageinfo.get(0).extmetadata().licenseUrl().value() : "";
+ }
+
+ static class ImageInfo {
+ @SuppressWarnings("unused") private Extmetadata extmetadata;
+ Extmetadata extmetadata() {
+ return extmetadata;
+ }
+ }
+
+ static class Extmetadata {
+ @SuppressWarnings({"unused", "CheckStyle"}) private License License;
+ @SuppressWarnings({"unused", "CheckStyle"}) private LicenseShortName
LicenseShortName;
+ @SuppressWarnings({"unused", "CheckStyle"}) private LicenseUrl
LicenseUrl;
+
+ License license() {
+ return License;
+ }
+
+ LicenseShortName licenseShortName() {
+ return LicenseShortName;
+ }
+
+ LicenseUrl licenseUrl() {
+ return LicenseUrl;
+ }
+ }
+
+ static class License {
+ @SuppressWarnings("unused") private String value;
+ String value() {
+ return value;
+ }
+ }
+
+ static class LicenseShortName {
+ @SuppressWarnings("unused") private String value;
+ String value() {
+ return value;
+ }
+ }
+
+ static class LicenseUrl {
+ @SuppressWarnings("unused") private String value;
+ String value() {
+ return value;
+ }
+ }
+}
diff --git a/app/src/main/java/org/wikipedia/gallery/GalleryItem.java
b/app/src/main/java/org/wikipedia/gallery/GalleryItem.java
index cd1ace8..f5841ca 100644
--- a/app/src/main/java/org/wikipedia/gallery/GalleryItem.java
+++ b/app/src/main/java/org/wikipedia/gallery/GalleryItem.java
@@ -7,7 +7,6 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.wikipedia.page.ImageLicense;
-import org.wikipedia.page.ImageLicenseFetchTask;
import java.util.HashMap;
import java.util.Iterator;
@@ -149,9 +148,21 @@
String value =
extmetadata.getJSONObject(key).getString("value");
metadata.put(key, value);
}
- license =
ImageLicenseFetchTask.imageLicenseFromMetadata(extmetadata);
+ license = imageLicenseFromMetadata(extmetadata);
} else {
license = new ImageLicense();
}
}
+
+ @NonNull
+ public static ImageLicense imageLicenseFromMetadata(JSONObject
extmetadata) {
+ return new ImageLicense(getValueForOptionalKey(extmetadata, "License"),
+ getValueForOptionalKey(extmetadata, "LicenseShortName"),
+ getValueForOptionalKey(extmetadata, "LicenseUrl"));
+ }
+
+ @NonNull
+ private static String getValueForOptionalKey(JSONObject object, String
key) {
+ return object.has(key) ? object.optJSONObject(key).optString("value")
: "";
+ }
}
diff --git a/app/src/main/java/org/wikipedia/page/ImageLicenseFetchClient.java
b/app/src/main/java/org/wikipedia/page/ImageLicenseFetchClient.java
new file mode 100644
index 0000000..2b3e0c9
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/page/ImageLicenseFetchClient.java
@@ -0,0 +1,78 @@
+package org.wikipedia.page;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.dataclient.mwapi.MwException;
+import org.wikipedia.dataclient.mwapi.MwQueryImageLicensePage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.dataclient.retrofit.MwCachedService;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import retrofit2.Call;
+import retrofit2.Response;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+
+public class ImageLicenseFetchClient {
+ @NonNull private MwCachedService<Service> cachedService = new
MwCachedService<>(Service.class);
+
+ public interface Callback {
+ void success(@NonNull Call<MwQueryResponse<QueryResult>> call,
@NonNull List<MwQueryImageLicensePage> results);
+ void failure(@NonNull Call<MwQueryResponse<QueryResult>> call,
@NonNull Throwable caught);
+ }
+
+ public Call<MwQueryResponse<QueryResult>> request(@NonNull WikiSite wiki,
+ @NonNull PageTitle title,
+ @NonNull Callback cb) {
+ List<PageTitle> titles = new ArrayList<>();
+ titles.add(title);
+
+ 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) {
+ if (response.body().success()) {
+ cb.success(call, response.body().query().pages());
+ } 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<MwQueryImageLicensePage> pages;
+ @Nullable List<MwQueryImageLicensePage> pages() {
+ return pages;
+ }
+ }
+
+ @VisibleForTesting interface Service {
+
@GET("w/api.php?action=query&format=json&formatversion=2&prop=imageinfo&iiprop=extmetadata")
+ Call<MwQueryResponse<QueryResult>> request(@NonNull @Query("titles")
String titles);
+ }
+}
diff --git a/app/src/main/java/org/wikipedia/page/ImageLicenseFetchTask.java
b/app/src/main/java/org/wikipedia/page/ImageLicenseFetchTask.java
deleted file mode 100644
index 43cc84c..0000000
--- a/app/src/main/java/org/wikipedia/page/ImageLicenseFetchTask.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.wikipedia.page;
-
-import android.support.annotation.NonNull;
-import android.util.Log;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mediawiki.api.json.Api;
-import org.mediawiki.api.json.RequestBuilder;
-import org.wikipedia.dataclient.WikiSite;
-
-/**
- * Fetch license info for a single image.
- */
-public class ImageLicenseFetchTask extends PageQueryTask<ImageLicense> {
- private static final String TAG = "ImageLicenseFetchTask";
-
- public ImageLicenseFetchTask(Api api, WikiSite wiki, PageTitle title) {
- super(api, wiki, title);
- }
-
- @Override
- public void buildQueryParams(RequestBuilder builder) {
- builder.param("prop", "imageinfo").param("iiprop", "extmetadata");
- }
-
- @Override
- public ImageLicense processPage(int pageId, PageTitle pageTitle,
JSONObject result) {
- try {
- JSONObject imageInfo = (JSONObject)
result.getJSONArray("imageinfo").get(0);
- return
imageLicenseFromMetadata(imageInfo.getJSONObject("extmetadata"));
- } catch (JSONException e) {
- Log.w(TAG, e);
- }
- return new ImageLicense();
- }
-
- @NonNull
- public static ImageLicense imageLicenseFromMetadata(JSONObject
extmetadata) {
- return new ImageLicense(getValueForOptionalKey(extmetadata, "License"),
- getValueForOptionalKey(extmetadata, "LicenseShortName"),
- getValueForOptionalKey(extmetadata, "LicenseUrl"));
- }
-
- @NonNull
- private static String getValueForOptionalKey(JSONObject object, String
key) {
- return object.has(key) ? object.optJSONObject(key).optString("value")
: "";
- }
-}
diff --git a/app/src/main/java/org/wikipedia/page/snippet/ShareHandler.java
b/app/src/main/java/org/wikipedia/page/snippet/ShareHandler.java
index 356b6fd..5b96470 100755
--- a/app/src/main/java/org/wikipedia/page/snippet/ShareHandler.java
+++ b/app/src/main/java/org/wikipedia/page/snippet/ShareHandler.java
@@ -25,8 +25,10 @@
import org.wikipedia.activity.ActivityUtil;
import org.wikipedia.analytics.ShareAFactFunnel;
import org.wikipedia.bridge.CommunicationBridge;
+import org.wikipedia.dataclient.mwapi.MwQueryImageLicensePage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.page.ImageLicense;
-import org.wikipedia.page.ImageLicenseFetchTask;
+import org.wikipedia.page.ImageLicenseFetchClient;
import org.wikipedia.page.NoDimBottomSheetDialog;
import org.wikipedia.page.Page;
import org.wikipedia.page.PageFragment;
@@ -42,7 +44,9 @@
import org.wikipedia.wiktionary.WiktionaryDialog;
import java.util.Arrays;
-import java.util.Map;
+import java.util.List;
+
+import retrofit2.Call;
import static org.wikipedia.analytics.ShareAFactFunnel.ShareMode;
@@ -126,29 +130,30 @@
final String selectedText = StringUtil.sanitizeText(input.toString());
final PageTitle title = fragment.getTitle();
- (new
ImageLicenseFetchTask(WikipediaApp.getInstance().getAPIForSite(title.getWikiSite()),
- title.getWikiSite(),
- new PageTitle("File:" +
fragment.getPage().getPageProperties().getLeadImageName(),
title.getWikiSite())) {
+ new ImageLicenseFetchClient().request(title.getWikiSite(),
+ new PageTitle("File:" +
fragment.getPage().getPageProperties().getLeadImageName(), title.getWikiSite()),
+ new ImageLicenseFetchClient.Callback() {
+ @Override public void success(@NonNull
Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call,
+ @NonNull
List<MwQueryImageLicensePage> pages) {
+ MwQueryImageLicensePage page = pages.get(0);
+ ImageLicense leadImageLicense = new
ImageLicense(page.imageLicense(),
+ page.imageLicenseShortName(),
+ page.imageLicenseUrl());
- @Override
- public void onFinish(@NonNull Map<PageTitle, ImageLicense> result)
{
- ImageLicense leadImageLicense = (ImageLicense)
result.values().toArray()[0];
+ final Bitmap snippetBitmap =
SnippetImage.getSnippetImage(fragment.getContext(),
+ fragment.getLeadImageBitmap(),
+ title.getDisplayText(),
+ fragment.getPage().isMainPage() ? "" :
StringUtils.capitalize(title.getDescription()),
+ selectedText,
+ leadImageLicense);
- final Bitmap snippetBitmap =
SnippetImage.getSnippetImage(fragment.getContext(),
- fragment.getLeadImageBitmap(),
- title.getDisplayText(),
- fragment.getPage().isMainPage() ? "" :
StringUtils.capitalize(title.getDescription()),
- selectedText,
- leadImageLicense);
+ fragment.showBottomSheet(new PreviewDialog(fragment,
snippetBitmap, title, selectedText, funnel));
+ }
- fragment.showBottomSheet(new PreviewDialog(fragment,
snippetBitmap, title, selectedText, funnel));
- }
-
- @Override
- public void onCatch(Throwable caught) {
- L.d("Error fetching image license info for " +
title.getDisplayText() + ": " + caught.getMessage(), caught);
- }
- }).execute();
+ @Override public void failure(@NonNull
Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call, @NonNull
Throwable caught) {
+ L.d("Error fetching image license info for " +
title.getDisplayText() + ": " + caught.getMessage(), caught);
+ }
+ });
}
/**
diff --git
a/app/src/test/java/org/wikipedia/page/ImageLicenseFetchClientTest.java
b/app/src/test/java/org/wikipedia/page/ImageLicenseFetchClientTest.java
new file mode 100644
index 0000000..2a6e5c0
--- /dev/null
+++ b/app/src/test/java/org/wikipedia/page/ImageLicenseFetchClientTest.java
@@ -0,0 +1,100 @@
+package org.wikipedia.page;
+
+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.MwQueryImageLicensePage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.dataclient.okhttp.HttpStatusException;
+import org.wikipedia.test.MockWebServerTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+import retrofit2.Call;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.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 ImageLicenseFetchClientTest extends MockWebServerTest{
+ private static final WikiSite WIKISITE_TEST =
WikiSite.forLanguageCode("test");
+ private static final PageTitle PAGE_TITLE_MARK_SELBY =
+ new
PageTitle("File:Mark_Selby_at_Snooker_German_Masters_(DerHexer)_2015-02-04_02.jpg",
+ WIKISITE_TEST);
+
+ @NonNull private final ImageLicenseFetchClient subject = new
ImageLicenseFetchClient();
+
+ @Test public void testRequestSuccess() throws Throwable {
+ enqueueFromFile("image_license.json");
+
+ ImageLicenseFetchClient.Callback cb =
mock(ImageLicenseFetchClient.Callback.class);
+ Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+ verify(cb).success(eq(call), captor.capture());
+
+ List<MwQueryImageLicensePage> result = captor.getValue();
+ MwQueryImageLicensePage mark = result.get(0);
+
+ assertThat(mark.title(), is("File:Mark Selby at Snooker German Masters
(DerHexer) 2015-02-04 02.jpg"));
+ assertThat(mark.imageLicense(), is("cc-by-sa-4.0"));
+ assertThat(mark.imageLicenseShortName(), is("CC BY-SA 4.0"));
+ assertThat(mark.imageLicenseUrl(),
is("http://creativecommons.org/licenses/by-sa/4.0"));
+ }
+
+ @Test public void testRequestResponseApiError() throws Throwable {
+ enqueueFromFile("api_error.json");
+
+ ImageLicenseFetchClient.Callback cb =
mock(ImageLicenseFetchClient.Callback.class);
+ Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, MwException.class);
+ }
+
+ @Test public void testRequestResponseFailure() throws Throwable {
+ enqueue404();
+
+ ImageLicenseFetchClient.Callback cb =
mock(ImageLicenseFetchClient.Callback.class);
+ Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, HttpStatusException.class);
+ }
+
+ @Test public void testRequestResponseMalformed() throws Throwable {
+ server().enqueue("'");
+
+ ImageLicenseFetchClient.Callback cb =
mock(ImageLicenseFetchClient.Callback.class);
+ Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, MalformedJsonException.class);
+ }
+
+ private void assertCallbackFailure(@NonNull
Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> call,
+ @NonNull
ImageLicenseFetchClient.Callback cb,
+ @NonNull Class<? extends Throwable>
throwable) {
+ //noinspection unchecked
+ verify(cb, never()).success(any(Call.class), any(List.class));
+ verify(cb).failure(eq(call), isA(throwable));
+ }
+
+ private Call<MwQueryResponse<ImageLicenseFetchClient.QueryResult>> request(
+ @NonNull ImageLicenseFetchClient.Callback cb) {
+ return subject.request(WIKISITE_TEST,
service(ImageLicenseFetchClient.Service.class),
+ Arrays.asList(PAGE_TITLE_MARK_SELBY), cb);
+ }
+}
diff --git a/app/src/test/res/raw/image_license.json
b/app/src/test/res/raw/image_license.json
new file mode 100644
index 0000000..79141bd
--- /dev/null
+++ b/app/src/test/res/raw/image_license.json
@@ -0,0 +1,109 @@
+{
+ "batchcomplete": true,
+ "query": {
+ "normalized": [
+ {
+ "fromencoded": false,
+ "from":
"File:Mark_Selby_at_Snooker_German_Masters_(DerHexer)_2015-02-04_02.jpg",
+ "to": "File:Mark Selby at Snooker German Masters (DerHexer) 2015-02-04
02.jpg"
+ }
+ ],
+ "pages": [
+ {
+ "ns": 6,
+ "title": "File:Mark Selby at Snooker German Masters (DerHexer)
2015-02-04 02.jpg",
+ "missing": true,
+ "known": true,
+ "imagerepository": "shared",
+ "imageinfo": [
+ {
+ "extmetadata": {
+ "DateTime": {
+ "value": "2015-02-11 20:27:39",
+ "source": "mediawiki-metadata",
+ "hidden": ""
+ },
+ "ObjectName": {
+ "value": "Mark Selby at Snooker German Masters (DerHexer)
2015-02-04 02",
+ "source": "mediawiki-metadata",
+ "hidden": ""
+ },
+ "CommonsMetadataExtension": {
+ "value": 1.2,
+ "source": "extension",
+ "hidden": ""
+ },
+ "Categories": {
+ "value": "Files by DerHexer|German Masters 2015-Day 1, Session
2|Images with extracted images|Mark Selby|Personality rights
warning|Self-published work|Uploaded with VicuñaUploader",
+ "source": "commons-categories",
+ "hidden": ""
+ },
+ "Assessments": {
+ "value": "",
+ "source": "commons-categories",
+ "hidden": ""
+ },
+ "ImageDescription": {
+ "value": "Picture taken in Berlin during the <a
href=\"https://en.wikipedia.org/wiki/2015_German_Masters\" class=\"extiw\"
title=\"en:2015 German Masters\">Snooker German Masters in 2015</a>. Mark
Selby.",
+ "source": "commons-desc-page"
+ },
+ "DateTimeOriginal": {
+ "value": "2015-02-04 15:19",
+ "source": "commons-desc-page"
+ },
+ "Credit": {
+ "value": "<span class=\"int-own-work\" lang=\"en\">Own
work</span>",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "Artist": {
+ "value": "<a
href=\"//commons.wikimedia.org/wiki/User:DerHexer\"
title=\"User:DerHexer\">DerHexer</a>",
+ "source": "commons-desc-page"
+ },
+ "LicenseShortName": {
+ "value": "CC BY-SA 4.0",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "UsageTerms": {
+ "value": "Creative Commons Attribution-Share Alike 4.0",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "AttributionRequired": {
+ "value": "true",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "Attribution": {
+ "value": "DerHexer, Wikimedia Commons, CC-by-sa 4.0",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "LicenseUrl": {
+ "value": "http://creativecommons.org/licenses/by-sa/4.0",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "Copyrighted": {
+ "value": "True",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "Restrictions": {
+ "value": "personality",
+ "source": "commons-desc-page",
+ "hidden": ""
+ },
+ "License": {
+ "value": "cc-by-sa-4.0",
+ "source": "commons-templates",
+ "hidden": ""
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/351692
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib6ad70b969507aaad7356fce2e2e9bf27aaaeddc
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Jcasariego <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits