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 8d16a1630..093984cbf 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 @@ -33,6 +33,10 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import org.mediawiki.api.ApiResult; +import org.mediawiki.api.MWApi; + +import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -41,8 +45,10 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledThreadPoolExecutor; +import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.upload.MwVolleyApi; @@ -73,6 +79,9 @@ public class CategorizationFragment extends Fragment { PrefixUpdater prefixUpdaterSub; MethodAUpdater methodAUpdaterSub; + private final ArrayList titleCatItems = new ArrayList(); + final CountDownLatch mergeLatch = new CountDownLatch(1); + private ContentProviderClient client; protected final static int SEARCH_CATS_LIMIT = 25; @@ -113,12 +122,48 @@ public class CategorizationFragment extends Fragment { } /** - * Retrieves recently-used categories and nearby categories, and merges them without duplicates. - * @return a list containing these categories + * Retrieves category suggestions from title input + * @return a list containing title-related categories + */ + protected ArrayList titleCatQuery() { + + TitleCategories titleCategoriesSub; + + //Retrieve the title that was saved when user tapped submit icon + SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity()); + String title = titleDesc.getString("Title", ""); + Log.d(TAG, "Title: " + title); + + //Override onPostExecute to access the results of async API call + titleCategoriesSub = new TitleCategories(title) { + @Override + protected void onPostExecute(ArrayList result) { + super.onPostExecute(result); + Log.d(TAG, "Results in onPostExecute: " + result); + titleCatItems.addAll(result); + Log.d(TAG, "TitleCatItems in onPostExecute: " + titleCatItems); + mergeLatch.countDown(); + } + }; + + Utils.executeAsyncTask(titleCategoriesSub); + Log.d(TAG, "TitleCatItems in titleCatQuery: " + titleCatItems); + + //Only return titleCatItems after API call has finished + try { + mergeLatch.await(); + } catch (InterruptedException e) { + Log.e(TAG, "Interrupted exception: ", e); + } + return titleCatItems; + } + + /** + * Retrieves recently-used categories + * @return a list containing recent categories */ protected ArrayList recentCatQuery() { ArrayList items = new ArrayList(); - Set mergedItems = new LinkedHashSet(); try { Cursor cursor = client.query( @@ -133,23 +178,49 @@ public class CategorizationFragment extends Fragment { items.add(cat.getName()); } cursor.close(); - - if (MwVolleyApi.GpsCatExists.getGpsCatExists() == true) { - //Log.d(TAG, "GPS cats found in CategorizationFragment.java" + MwVolleyApi.getGpsCat().toString()); - List gpsItems = new ArrayList(MwVolleyApi.getGpsCat()); - //Log.d(TAG, "GPS items: " + gpsItems.toString()); - - mergedItems.addAll(gpsItems); - } - - mergedItems.addAll(items); } catch (RemoteException e) { throw new RuntimeException(e); } + return items; + } + + /** + * Merges nearby categories, categories suggested based on title, and recent categories... without duplicates. + * @return a list containing merged categories + */ + protected ArrayList mergeItems() { + + Set mergedItems = new LinkedHashSet(); + + Log.d(TAG, "Calling APIs for GPS cats, title cats and recent cats..."); + + List gpsItems = new ArrayList(); + if (MwVolleyApi.GpsCatExists.getGpsCatExists()) { + gpsItems.addAll(MwVolleyApi.getGpsCat()); + } + List titleItems = new ArrayList(titleCatQuery()); + List recentItems = new ArrayList(recentCatQuery()); + + //Await results of titleItems, which is likely to come in last + try { + mergeLatch.await(); + Log.d(TAG, "Waited for merge"); + } catch (InterruptedException e) { + Log.e(TAG, "Interrupted Exception: ", e); + } + + mergedItems.addAll(gpsItems); + Log.d(TAG, "Adding GPS items: " + gpsItems); + mergedItems.addAll(titleItems); + Log.d(TAG, "Adding title items: " + titleItems); + mergedItems.addAll(recentItems); + Log.d(TAG, "Adding recent items: " + recentItems); //Needs to be an ArrayList and not a List unless we want to modify a big portion of preexisting code ArrayList mergedItemsList = new ArrayList(mergedItems); + Log.d(TAG, "Merged item list: " + mergedItemsList); + return mergedItemsList; } diff --git a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java index 54f6771fb..5ac3f3bf2 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java @@ -42,7 +42,7 @@ public class MethodAUpdater extends AsyncTask> { protected ArrayList doInBackground(Void... voids) { //If user hasn't typed anything in yet, get GPS and recent items if(TextUtils.isEmpty(filter)) { - return catFragment.recentCatQuery(); + return catFragment.mergeItems(); } //if user types in something that is in cache, return cached category diff --git a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java index 3a4005294..b095bfe6a 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java @@ -45,7 +45,7 @@ public class PrefixUpdater extends AsyncTask> { protected ArrayList doInBackground(Void... voids) { //If user hasn't typed anything in yet, get GPS and recent items if(TextUtils.isEmpty(filter)) { - return catFragment.recentCatQuery(); + return catFragment.mergeItems(); } //if user types in something that is in cache, return cached category diff --git a/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java new file mode 100644 index 000000000..7d5a7607e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java @@ -0,0 +1,73 @@ +package fr.free.nrw.commons.category; + +import android.os.AsyncTask; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import org.mediawiki.api.ApiResult; +import org.mediawiki.api.MWApi; + +import java.io.IOException; +import java.util.ArrayList; + +import fr.free.nrw.commons.CommonsApplication; + +/** + * Sends asynchronous queries to the Commons MediaWiki API to retrieve categories that are related to + * the title entered in previous screen. The 'srsearch' action-specific parameter is used for this + * purpose. This class should be subclassed in CategorizationFragment.java to add the results to recent and GPS cats. + */ +public class TitleCategories extends AsyncTask> { + + private final static int SEARCH_CATS_LIMIT = 25; + private static final String TAG = TitleCategories.class.getName(); + private String title; + + public TitleCategories(String title) { + super(); + this.title = title; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected ArrayList doInBackground(Void... voids) { + + MWApi api = CommonsApplication.createMWApi(); + ApiResult result; + ArrayList items = new ArrayList<>(); + + //URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch= + try { + result = api.action("query") + .param("format", "xml") + .param("list", "search") + .param("srwhat", "text") + .param("srnamespace", "14") + .param("srlimit", SEARCH_CATS_LIMIT) + .param("srsearch", title) + .get(); + Log.d(TAG, "Searching for cats for title: " + result.toString()); + } catch (IOException e) { + Log.e(TAG, "IO Exception: ", e); + //Return empty arraylist + return items; + } + + ArrayList categoryNodes = result.getNodes("/api/query/search/p/@title"); + for(ApiResult categoryNode: categoryNodes) { + String cat = categoryNode.getDocument().getTextContent(); + String catString = cat.replace("Category:", ""); + items.add(catString); + } + + Log.d(TAG, "Title cat query results: " + items); + + return items; + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java index 0d5d4ee3f..6efa05b14 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java @@ -52,12 +52,13 @@ public class SingleUploadFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + //What happens when the 'submit' icon is tapped case R.id.menu_upload_single: String title = titleEdit.getText().toString(); String desc = descEdit.getText().toString(); - //Save the values of these fields in short-lived cache so next time this fragment is loaded, we can access these + //Save the title/desc in short-lived cache so next time this fragment is loaded, we can access these SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = titleDesc.edit(); editor.putString("Title", title);