From b7215c580f66f3ff9f56f2dd546004376573dc7f Mon Sep 17 00:00:00 2001 From: Mikel Date: Sun, 6 Aug 2017 19:58:58 +0100 Subject: [PATCH] Migrate network tasks to RxJava --- .../category/CategorizationFragment.java | 122 ++++++---------- .../mwapi/ApacheHttpClientMediaWikiApi.java | 137 +++++++++++------- .../free/nrw/commons/mwapi/MediaWikiApi.java | 7 +- 3 files changed, 133 insertions(+), 133 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java index 39248c062..4ecb27a8b 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java @@ -23,7 +23,6 @@ import com.jakewharton.rxbinding2.view.RxView; import com.jakewharton.rxbinding2.widget.RxTextView; import com.pedrogomez.renderers.RVRendererAdapter; -import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -36,10 +35,8 @@ import butterknife.ButterKnife; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.data.Category; -import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.upload.MwVolleyApi; import io.reactivex.Observable; -import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import timber.log.Timber; @@ -194,7 +191,7 @@ public class CategorizationFragment extends Fragment { rootView.requestFocus(); rootView.setOnKeyListener((v, keyCode, event) -> { if (event.getAction() == ACTION_UP && keyCode == KEYCODE_BACK) { - backButtonDialog(); + showBackButtonDialog(); return true; } return false; @@ -224,25 +221,12 @@ public class CategorizationFragment extends Fragment { public boolean onOptionsItemSelected(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.menu_save_categories: - //If no categories selected, display warning to user - if (selectedCategories.size() == 0) { - new AlertDialog.Builder(getActivity()) - .setMessage("Images without categories are rarely usable. " - + "Are you sure you want to submit without selecting " - + "categories?") - .setTitle("No Categories Selected") - .setPositiveButton("No, go back", (dialog, id) -> { - //Exit menuItem so user can select their categories - }) - .setNegativeButton("Yes, submit", (dialog, id) -> { - //Proceed to submission - onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories)); - }) - .create() - .show(); - } else { - //Proceed to submission + if (selectedCategories.size() > 0) { + //Some categories selected, proceed to submission onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories)); + } else { + //No categories selected, prompt the user to select some + showConfirmationDialog(); } return true; default: @@ -271,7 +255,7 @@ public class CategorizationFragment extends Fragment { return Observable.fromIterable( MwVolleyApi.GpsCatExists.getGpsCatExists() ? MwVolleyApi.getGpsCat() : new ArrayList<>()) - .map(s -> new CategoryItem(s, false)); + .map(name -> new CategoryItem(name, false)); } private Observable titleCategories() { @@ -279,10 +263,9 @@ public class CategorizationFragment extends Fragment { SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity()); String title = titleDesc.getString("Title", ""); - return Observable.just(title) - .observeOn(Schedulers.io()) - .flatMapIterable(s -> titleCatQuery(s)) - .map(s -> new CategoryItem(s, false)); + return CommonsApplication.getInstance().getMWApi() + .searchTitles(title, SEARCH_CATS_LIMIT) + .map(name -> new CategoryItem(name, false)); } private Observable recentCategories() { @@ -291,62 +274,35 @@ public class CategorizationFragment extends Fragment { } private Observable search(String term) { - return Single.just(term) - .map(s -> { - //If user hasn't typed anything in yet, get GPS and recent items - if (TextUtils.isEmpty(s)) { - return new ArrayList(); - } + //If user hasn't typed anything in yet, get GPS and recent items + if (TextUtils.isEmpty(term)) { + return Observable.empty(); + } - //if user types in something that is in cache, return cached category - if (categoriesCache.containsKey(s)) { - return categoriesCache.get(s); - } + //if user types in something that is in cache, return cached category + if (categoriesCache.containsKey(term)) { + return Observable.fromIterable(categoriesCache.get(term)) + .map(name -> new CategoryItem(name, false)); + } - //otherwise if user has typed something in that isn't in cache, search API for matching categories - //URL: https://commons.wikimedia.org/w/api.php?action=query&list=allcategories&acprefix=filter&aclimit=25 - MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); - List categories = new ArrayList<>(); - try { - categories = api.allCategories(SEARCH_CATS_LIMIT, s); - Timber.d("Prefix URL filter %s", categories); - } catch (IOException e) { - Timber.e(e, "IO Exception: "); - //Return empty arraylist - return categories; - } - - Timber.d("Found categories from Prefix search, waiting for filter"); - return categories; - }) - .flatMapObservable(Observable::fromIterable) - .map(s -> new CategoryItem(s, false)); + //otherwise if user has typed something in that isn't in cache, search API for matching categories + return CommonsApplication.getInstance().getMWApi() + .allCategories(term, SEARCH_CATS_LIMIT) + .map(name -> new CategoryItem(name, false)); } private Observable search2(String term) { - return Single.just(term) - .map(s -> { - //If user hasn't typed anything in yet, get GPS and recent items - if (TextUtils.isEmpty(s)) { - return new ArrayList(); - } + //If user hasn't typed anything in yet, get GPS and recent items + if (TextUtils.isEmpty(term)) { + return Observable.empty(); + } - MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); - - //URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch= - try { - return api.searchCategories(SEARCH_CATS_LIMIT, term); - } catch (IOException e) { - Timber.e(e, "IO Exception: "); - return new ArrayList(); - } - }) - .flatMapObservable(Observable::fromIterable) + return CommonsApplication.getInstance().getMWApi() + .searchCategories(term, SEARCH_CATS_LIMIT) .map(s -> new CategoryItem(s, false)); } private boolean containsYear(String items) { - //Check for current and previous year to exclude these categories from removal Calendar now = Calendar.getInstance(); int year = now.get(Calendar.YEAR); @@ -356,7 +312,6 @@ public class CategorizationFragment extends Fragment { String prevYearInString = String.valueOf(prevYear); Timber.d("Previous year: %s", prevYearInString); - //Check if s contains a 4-digit word anywhere within the string (.* is wildcard) //And that s does not equal the current year or previous year //And if it is an irrelevant category such as Media_needing_categories_as_of_16_June_2017(Issue #750) @@ -368,7 +323,7 @@ public class CategorizationFragment extends Fragment { return selectedCategories.size(); } - public void backButtonDialog() { + public void showBackButtonDialog() { new AlertDialog.Builder(getActivity()) .setMessage("Are you sure you want to go back? The image will not " + "have any categories saved.") @@ -380,4 +335,21 @@ public class CategorizationFragment extends Fragment { .create() .show(); } + + public void showConfirmationDialog() { + new AlertDialog.Builder(getActivity()) + .setMessage("Images without categories are rarely usable. " + + "Are you sure you want to submit without selecting " + + "categories?") + .setTitle("No Categories Selected") + .setPositiveButton("No, go back", (dialog, id) -> { + //Exit menuItem so user can select their categories + }) + .setNegativeButton("Yes, submit", (dialog, id) -> { + //Proceed to submission + onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories)); + }) + .create() + .show(); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 60fefe036..7af42b0fe 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -35,6 +35,7 @@ import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.PageTitle; import fr.free.nrw.commons.Utils; import in.yuvi.http.fluent.Http; +import io.reactivex.Observable; import io.reactivex.Single; import timber.log.Timber; @@ -205,78 +206,104 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { @Override @NonNull - public List searchCategories(int searchCatsLimit, String filterValue) throws IOException { - List categoryNodes = api.action("query") - .param("format", "xml") - .param("list", "search") - .param("srwhat", "text") - .param("srnamespace", "14") - .param("srlimit", searchCatsLimit) - .param("srsearch", filterValue) - .get() - .getNodes("/api/query/search/p/@title"); + public Observable searchCategories(String filterValue, int searchCatsLimit) { + return Single.fromCallable(() -> { + List categoryNodes = null; + try { + categoryNodes = api.action("query") + .param("format", "xml") + .param("list", "search") + .param("srwhat", "text") + .param("srnamespace", "14") + .param("srlimit", searchCatsLimit) + .param("srsearch", filterValue) + .get() + .getNodes("/api/query/search/p/@title"); + } catch (IOException e) { + Timber.e("Failed to obtain searchCategories", e); + } - if (categoryNodes == null) { - return Collections.emptyList(); - } + if (categoryNodes == null) { + return new ArrayList(); + } - List categories = new ArrayList<>(); - for (ApiResult categoryNode : categoryNodes) { - String cat = categoryNode.getDocument().getTextContent(); - String catString = cat.replace("Category:", ""); - categories.add(catString); - } + List categories = new ArrayList<>(); + for (ApiResult categoryNode : categoryNodes) { + String cat = categoryNode.getDocument().getTextContent(); + String catString = cat.replace("Category:", ""); + categories.add(catString); + } - return categories; + return categories; + }) + .flatMapObservable(list -> Observable.fromIterable(list)); } @Override @NonNull - public List allCategories(int searchCatsLimit, String filterValue) throws IOException { - ArrayList categoryNodes = api.action("query") - .param("list", "allcategories") - .param("acprefix", filterValue) - .param("aclimit", searchCatsLimit) - .get() - .getNodes("/api/query/allcategories/c"); + public Observable allCategories(String filterValue, int searchCatsLimit) { + return Single.fromCallable(() -> { + ArrayList categoryNodes = null; + try { + categoryNodes = api.action("query") + .param("list", "allcategories") + .param("acprefix", filterValue) + .param("aclimit", searchCatsLimit) + .get() + .getNodes("/api/query/allcategories/c"); + } catch (IOException e) { + Timber.e("Failed to obtain allCategories", e); + } - if (categoryNodes == null) { - return Collections.emptyList(); - } + if (categoryNodes == null) { + return new ArrayList(); + } - List categories = new ArrayList<>(); - for (ApiResult categoryNode : categoryNodes) { - categories.add(categoryNode.getDocument().getTextContent()); - } + List categories = new ArrayList<>(); + for (ApiResult categoryNode : categoryNodes) { + categories.add(categoryNode.getDocument().getTextContent()); + } - return categories; + return categories; + }) + .flatMapObservable(list -> Observable.fromIterable(list)); } @Override @NonNull - public List searchTitles(int searchCatsLimit, String title) throws IOException { - ArrayList categoryNodes = api.action("query") - .param("format", "xml") - .param("list", "search") - .param("srwhat", "text") - .param("srnamespace", "14") - .param("srlimit", searchCatsLimit) - .param("srsearch", title) - .get() - .getNodes("/api/query/search/p/@title"); + public Observable searchTitles(String title, int searchCatsLimit) { + return Single.fromCallable(() -> { + ArrayList categoryNodes = null; - if (categoryNodes == null) { - return Collections.emptyList(); - } + try { + categoryNodes = api.action("query") + .param("format", "xml") + .param("list", "search") + .param("srwhat", "text") + .param("srnamespace", "14") + .param("srlimit", searchCatsLimit) + .param("srsearch", title) + .get() + .getNodes("/api/query/search/p/@title"); + } catch (IOException e) { + Timber.e("Failed to obtain searchTitles", e); + return new ArrayList(); + } - List titleCategories = new ArrayList<>(); - for (ApiResult categoryNode : categoryNodes) { - String cat = categoryNode.getDocument().getTextContent(); - String catString = cat.replace("Category:", ""); - titleCategories.add(catString); - } + if (categoryNodes == null) { + return Collections.emptyList(); + } - return titleCategories; + List titleCategories = new ArrayList<>(); + for (ApiResult categoryNode : categoryNodes) { + String cat = categoryNode.getDocument().getTextContent(); + String catString = cat.replace("Category:", ""); + titleCategories.add(catString); + } + + return titleCategories; + }) + .flatMapObservable(list -> Observable.fromIterable(list)); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java index c50dd56d2..292c0a5de 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; +import io.reactivex.Observable; import io.reactivex.Single; public interface MediaWikiApi { @@ -38,13 +39,13 @@ public interface MediaWikiApi { MediaResult fetchMediaByFilename(String filename) throws IOException; @NonNull - List searchCategories(int searchCatsLimit, String filterValue) throws IOException; + Observable searchCategories(String filterValue, int searchCatsLimit); @NonNull - List allCategories(int searchCatsLimit, String filter) throws IOException; + Observable allCategories(String filter, int searchCatsLimit); @NonNull - List searchTitles(int searchCatsLimit, String title) throws IOException; + Observable searchTitles(String title, int searchCatsLimit); @Nullable String revisionsByFilename(String filename) throws IOException;