|
| 1 | +package fr.free.nrw.commons.upload; |
| 2 | + |
| 3 | +import android.support.annotation.NonNull; |
| 4 | + |
| 5 | +import com.google.gson.Gson; |
| 6 | + |
| 7 | +import java.io.IOException; |
| 8 | +import java.util.ArrayList; |
| 9 | +import java.util.HashSet; |
| 10 | +import java.util.List; |
| 11 | +import java.util.Set; |
| 12 | + |
| 13 | +import javax.inject.Inject; |
| 14 | +import javax.inject.Named; |
| 15 | + |
| 16 | +import okhttp3.Call; |
| 17 | +import okhttp3.Callback; |
| 18 | +import okhttp3.HttpUrl; |
| 19 | +import okhttp3.OkHttpClient; |
| 20 | +import okhttp3.Request; |
| 21 | +import okhttp3.ResponseBody; |
| 22 | +import timber.log.Timber; |
| 23 | + |
| 24 | +/** |
| 25 | + * Uses the OkHttp library to implement asynchronous calls to the Commons MediaWiki API to match |
| 26 | + * GPS coordinates with nearby Commons categories. Parses the results using GSON to obtain a list |
| 27 | + * of relevant categories. |
| 28 | + */ |
| 29 | +public class CategoryApi { |
| 30 | + |
| 31 | + private static Set<String> categorySet; |
| 32 | + private static List<String> categoryList; |
| 33 | + private final OkHttpClient okHttpClient; |
| 34 | + private final HttpUrl mwUrl; |
| 35 | + private final Gson gson; |
| 36 | + |
| 37 | + @Inject |
| 38 | + public CategoryApi(OkHttpClient okHttpClient, @Named("commons_mediawiki_url") HttpUrl mwUrl, Gson gson) { |
| 39 | + this.okHttpClient = okHttpClient; |
| 40 | + this.mwUrl = mwUrl; |
| 41 | + this.gson = gson; |
| 42 | + categorySet = new HashSet<>(); |
| 43 | + } |
| 44 | + |
| 45 | + public static List<String> getGpsCat() { |
| 46 | + return categoryList; |
| 47 | + } |
| 48 | + |
| 49 | + public static void setGpsCat(List<String> cachedList) { |
| 50 | + categoryList = new ArrayList<>(); |
| 51 | + categoryList.addAll(cachedList); |
| 52 | + Timber.d("Setting GPS cats from cache: %s", categoryList); |
| 53 | + } |
| 54 | + |
| 55 | + public void request(String coords) { |
| 56 | + String apiUrl = buildUrl(coords); |
| 57 | + Timber.d("URL: %s", apiUrl); |
| 58 | + |
| 59 | + Call call = okHttpClient.newCall(new Request.Builder().get().url(apiUrl).build()); |
| 60 | + call.enqueue(new Callback() { |
| 61 | + @Override |
| 62 | + public void onFailure(@NonNull Call call, @NonNull IOException e) { |
| 63 | + Timber.e(e); |
| 64 | + GpsCatExists.setGpsCatExists(false); |
| 65 | + } |
| 66 | + |
| 67 | + @Override |
| 68 | + public void onResponse(@NonNull Call call, @NonNull okhttp3.Response response) { |
| 69 | + categoryList = new ArrayList<>(); |
| 70 | + categorySet = new HashSet<>(); |
| 71 | + ResponseBody body = response.body(); |
| 72 | + if (body == null) { |
| 73 | + return; |
| 74 | + } |
| 75 | + QueryResponse queryResponse = gson.fromJson(body.charStream(), QueryResponse.class); |
| 76 | + if (queryResponse != null && queryResponse.query != null && queryResponse.query.pages != null) { |
| 77 | + for (Page page : queryResponse.query.pages) { |
| 78 | + if (page.categories != null) { |
| 79 | + for (Category category : page.categories) { |
| 80 | + String categoryString = category.title.replace("Category:", ""); |
| 81 | + categorySet.add(categoryString); |
| 82 | + } |
| 83 | + categoryList = new ArrayList<>(categorySet); |
| 84 | + } |
| 85 | + } |
| 86 | + } |
| 87 | + GpsCatExists.setGpsCatExists(!categorySet.isEmpty()); |
| 88 | + } |
| 89 | + }); |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Builds URL with image coords for MediaWiki API calls |
| 94 | + * Example URL: https://commons.wikimedia.org/w/api.php?action=query&prop=categories|coordinates|pageprops&format=json&clshow=!hidden&coprop=type|name|dim|country|region|globe&codistancefrompoint=38.11386944444445|13.356263888888888&generator=geosearch&redirects=&ggscoord=38.11386944444445|1.356263888888888&ggsradius=100&ggslimit=10&ggsnamespace=6&ggsprop=type|name|dim|country|region|globe&ggsprimary=all&formatversion=2 |
| 95 | + * |
| 96 | + * @param coords Coordinates to build query with |
| 97 | + * @return URL for API query |
| 98 | + */ |
| 99 | + private String buildUrl(String coords) { |
| 100 | + return mwUrl.newBuilder() |
| 101 | + .addPathSegment("w") |
| 102 | + .addPathSegment("api.php") |
| 103 | + .addQueryParameter("action", "query") |
| 104 | + .addQueryParameter("prop", "categories|coordinates|pageprops") |
| 105 | + .addQueryParameter("format", "json") |
| 106 | + .addQueryParameter("clshow", "!hidden") |
| 107 | + .addQueryParameter("coprop", "type|name|dim|country|region|globe") |
| 108 | + .addQueryParameter("codistancefrompoint", coords) |
| 109 | + .addQueryParameter("generator", "geosearch") |
| 110 | + .addQueryParameter("ggscoord", coords) |
| 111 | + .addQueryParameter("ggsradius", "10000") |
| 112 | + .addQueryParameter("ggslimit", "10") |
| 113 | + .addQueryParameter("ggsnamespace", "6") |
| 114 | + .addQueryParameter("ggsprop", "type|name|dim|country|region|globe") |
| 115 | + .addQueryParameter("ggsprimary", "all") |
| 116 | + .addQueryParameter("formatversion", "2") |
| 117 | + .build().toString(); |
| 118 | + } |
| 119 | + |
| 120 | + public static class GpsCatExists { |
| 121 | + private static boolean gpsCatExists; |
| 122 | + |
| 123 | + public static void setGpsCatExists(boolean gpsCat) { |
| 124 | + gpsCatExists = gpsCat; |
| 125 | + } |
| 126 | + |
| 127 | + public static boolean getGpsCatExists() { |
| 128 | + return gpsCatExists; |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + private static class QueryResponse { |
| 133 | + public Query query; |
| 134 | + |
| 135 | + public QueryResponse() { |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + private static class Query { |
| 140 | + public Page[] pages; |
| 141 | + |
| 142 | + public Query() { |
| 143 | + pages = new Page[0]; |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + private static class Page { |
| 148 | + public String title; |
| 149 | + public Category[] categories; |
| 150 | + public Category category; |
| 151 | + |
| 152 | + public Page() { |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + private static class Category { |
| 157 | + public String title; |
| 158 | + |
| 159 | + public Category() { |
| 160 | + } |
| 161 | + } |
| 162 | +} |
| 163 | + |
| 164 | + |
| 165 | + |
0 commit comments