Migrated recentlanguages and repository module from Java to Kotlin (#5948)

* Rename .java to .kt

* Migrated recentlanguages module to Kotlin

* Rename .java to .kt

* Migrated repository module to Kotlin
This commit is contained in:
Saifuddin Adenwala 2024-11-22 19:28:16 +05:30 committed by GitHub
parent 088dd2479e
commit fe347c21fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 825 additions and 798 deletions

View file

@ -1,122 +0,0 @@
package fr.free.nrw.commons.recentlanguages;
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.COLUMN_NAME;
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.TABLE_NAME;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.data.DBOpenHelper;
import fr.free.nrw.commons.di.CommonsDaggerContentProvider;
import javax.inject.Inject;
import timber.log.Timber;
/**
* Content provider of recently used languages
*/
public class RecentLanguagesContentProvider extends CommonsDaggerContentProvider {
private static final String BASE_PATH = "recent_languages";
public static final Uri BASE_URI =
Uri.parse("content://" + BuildConfig.RECENT_LANGUAGE_AUTHORITY + "/" + BASE_PATH);
/**
* Append language code to the base uri
* @param languageCode Code of a language
*/
public static Uri uriForCode(final String languageCode) {
return Uri.parse(BASE_URI + "/" + languageCode);
}
@Inject
DBOpenHelper dbOpenHelper;
@Override
public String getType(@NonNull final Uri uri) {
return null;
}
/**
* Queries the SQLite database for the recently used languages
* @param uri : contains the uri for recently used languages
* @param projection : contains the all fields of the table
* @param selection : handles Where
* @param selectionArgs : the condition of Where clause
* @param sortOrder : ascending or descending
*/
@Override
public Cursor query(@NonNull final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(TABLE_NAME);
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
final Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
/**
* Handles the update query of local SQLite Database
* @param uri : contains the uri for recently used languages
* @param contentValues : new values to be entered to db
* @param selection : handles Where
* @param selectionArgs : the condition of Where clause
*/
@Override
public int update(@NonNull final Uri uri, final ContentValues contentValues,
final String selection, final String[] selectionArgs) {
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
final int rowsUpdated;
if (TextUtils.isEmpty(selection)) {
final int id = Integer.parseInt(uri.getLastPathSegment());
rowsUpdated = sqlDB.update(TABLE_NAME,
contentValues,
COLUMN_NAME + " = ?",
new String[]{String.valueOf(id)});
} else {
throw new IllegalArgumentException(
"Parameter `selection` should be empty when updating an ID");
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
/**
* Handles the insertion of new recently used languages record to local SQLite Database
* @param uri : contains the uri for recently used languages
* @param contentValues : new values to be entered to db
*/
@Override
public Uri insert(@NonNull final Uri uri, final ContentValues contentValues) {
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
final long id = sqlDB.insert(TABLE_NAME, null, contentValues);
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(BASE_URI + "/" + id);
}
/**
* Handles the deletion of new recently used languages record to local SQLite Database
* @param uri : contains the uri for recently used languages
*/
@Override
public int delete(@NonNull final Uri uri, final String s, final String[] strings) {
final int rows;
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Timber.d("Deleting recently used language %s", uri.getLastPathSegment());
rows = db.delete(
TABLE_NAME,
"language_code = ?",
new String[]{uri.getLastPathSegment()}
);
getContext().getContentResolver().notifyChange(uri, null);
return rows;
}
}

View file

@ -0,0 +1,142 @@
package fr.free.nrw.commons.recentlanguages
import android.content.ContentValues
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteQueryBuilder
import android.net.Uri
import android.text.TextUtils
import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.data.DBOpenHelper
import fr.free.nrw.commons.di.CommonsDaggerContentProvider
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.COLUMN_NAME
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.TABLE_NAME
import javax.inject.Inject
import timber.log.Timber
/**
* Content provider of recently used languages
*/
class RecentLanguagesContentProvider : CommonsDaggerContentProvider() {
companion object {
private const val BASE_PATH = "recent_languages"
val BASE_URI: Uri =
Uri.parse(
"content://${BuildConfig.RECENT_LANGUAGE_AUTHORITY}/$BASE_PATH"
)
/**
* Append language code to the base URI
* @param languageCode Code of a language
*/
@JvmStatic
fun uriForCode(languageCode: String): Uri {
return Uri.parse("$BASE_URI/$languageCode")
}
}
@Inject
lateinit var dbOpenHelper: DBOpenHelper
override fun getType(uri: Uri): String? {
return null
}
/**
* Queries the SQLite database for the recently used languages
* @param uri : contains the URI for recently used languages
* @param projection : contains all fields of the table
* @param selection : handles WHERE
* @param selectionArgs : the condition of WHERE clause
* @param sortOrder : ascending or descending
*/
override fun query(
uri: Uri,
projection: Array<String>?,
selection: String?,
selectionArgs: Array<String>?,
sortOrder: String?
): Cursor? {
val queryBuilder = SQLiteQueryBuilder()
queryBuilder.tables = TABLE_NAME
val db = dbOpenHelper.readableDatabase
val cursor = queryBuilder.query(
db,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
)
cursor.setNotificationUri(context?.contentResolver, uri)
return cursor
}
/**
* Handles the update query of local SQLite Database
* @param uri : contains the URI for recently used languages
* @param contentValues : new values to be entered to the database
* @param selection : handles WHERE
* @param selectionArgs : the condition of WHERE clause
*/
override fun update(
uri: Uri,
contentValues: ContentValues?,
selection: String?,
selectionArgs: Array<String>?
): Int {
val sqlDB = dbOpenHelper.writableDatabase
val rowsUpdated: Int
if (selection.isNullOrEmpty()) {
val id = uri.lastPathSegment?.toInt()
?: throw IllegalArgumentException("Invalid URI: $uri")
rowsUpdated = sqlDB.update(
TABLE_NAME,
contentValues,
"$COLUMN_NAME = ?",
arrayOf(id.toString())
)
} else {
throw IllegalArgumentException("Parameter `selection` should be empty when updating an ID")
}
context?.contentResolver?.notifyChange(uri, null)
return rowsUpdated
}
/**
* Handles the insertion of new recently used languages record to local SQLite Database
* @param uri : contains the URI for recently used languages
* @param contentValues : new values to be entered to the database
*/
override fun insert(uri: Uri, contentValues: ContentValues?): Uri? {
val sqlDB = dbOpenHelper.writableDatabase
val id = sqlDB.insert(
TABLE_NAME,
null,
contentValues
)
context?.contentResolver?.notifyChange(uri, null)
return Uri.parse("$BASE_URI/$id")
}
/**
* Handles the deletion of a recently used languages record from local SQLite Database
* @param uri : contains the URI for recently used languages
*/
override fun delete(uri: Uri, s: String?, strings: Array<String>?): Int {
val db = dbOpenHelper.readableDatabase
Timber.d("Deleting recently used language %s", uri.lastPathSegment)
val rows = db.delete(
TABLE_NAME,
"language_code = ?",
arrayOf(uri.lastPathSegment)
)
context?.contentResolver?.notifyChange(uri, null)
return rows
}
}

View file

@ -1,204 +0,0 @@
package fr.free.nrw.commons.recentlanguages;
import android.annotation.SuppressLint;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.RemoteException;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
/**
* Handles database operations for recently used languages
*/
@Singleton
public class RecentLanguagesDao {
private final Provider<ContentProviderClient> clientProvider;
@Inject
public RecentLanguagesDao
(@Named("recent_languages") final Provider<ContentProviderClient> clientProvider) {
this.clientProvider = clientProvider;
}
/**
* Find all persisted recently used languages on database
* @return list of recently used languages
*/
public List<Language> getRecentLanguages() {
final List<Language> languages = new ArrayList<>();
final ContentProviderClient db = clientProvider.get();
try (final Cursor cursor = db.query(
RecentLanguagesContentProvider.BASE_URI,
RecentLanguagesDao.Table.ALL_FIELDS,
null,
new String[]{},
null)) {
if(cursor != null && cursor.moveToLast()) {
do {
languages.add(fromCursor(cursor));
} while (cursor.moveToPrevious());
}
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
return languages;
}
/**
* Add a Language to database
* @param language : Language to add
*/
public void addRecentLanguage(final Language language) {
final ContentProviderClient db = clientProvider.get();
try {
db.insert(RecentLanguagesContentProvider.BASE_URI, toContentValues(language));
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
}
/**
* Delete a language from database
* @param languageCode : code of the Language to delete
*/
public void deleteRecentLanguage(final String languageCode) {
final ContentProviderClient db = clientProvider.get();
try {
db.delete(RecentLanguagesContentProvider.uriForCode(languageCode), null, null);
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
}
/**
* Find a language from database based on its name
* @param languageCode : code of the Language to find
* @return boolean : is language in database ?
*/
public boolean findRecentLanguage(final String languageCode) {
if (languageCode == null) { //Avoiding NPE's
return false;
}
final ContentProviderClient db = clientProvider.get();
try (final Cursor cursor = db.query(
RecentLanguagesContentProvider.BASE_URI,
RecentLanguagesDao.Table.ALL_FIELDS,
Table.COLUMN_CODE + "=?",
new String[]{languageCode},
null
)) {
if (cursor != null && cursor.moveToFirst()) {
return true;
}
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
return false;
}
/**
* It creates an Recent Language object from data stored in the SQLite DB by using cursor
* @param cursor cursor
* @return Language object
*/
@NonNull
@SuppressLint("Range")
Language fromCursor(final Cursor cursor) {
// Hardcoding column positions!
final String languageName = cursor.getString(cursor.getColumnIndex(Table.COLUMN_NAME));
final String languageCode = cursor.getString(cursor.getColumnIndex(Table.COLUMN_CODE));
return new Language(languageName, languageCode);
}
/**
* Takes data from Language and create a content value object
* @param recentLanguage recently used language
* @return ContentValues
*/
private ContentValues toContentValues(final Language recentLanguage) {
final ContentValues cv = new ContentValues();
cv.put(Table.COLUMN_NAME, recentLanguage.getLanguageName());
cv.put(Table.COLUMN_CODE, recentLanguage.getLanguageCode());
return cv;
}
/**
* This class contains the database table architecture for recently used languages,
* It also contains queries and logic necessary to the create, update, delete this table.
*/
public static final class Table {
public static final String TABLE_NAME = "recent_languages";
static final String COLUMN_NAME = "language_name";
static final String COLUMN_CODE = "language_code";
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
public static final String[] ALL_FIELDS = {
COLUMN_NAME,
COLUMN_CODE
};
static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_NAME + " STRING,"
+ COLUMN_CODE + " STRING PRIMARY KEY"
+ ");";
/**
* This method creates a LanguagesTable in SQLiteDatabase
* @param db SQLiteDatabase
*/
public static void onCreate(final SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_STATEMENT);
}
/**
* This method deletes LanguagesTable from SQLiteDatabase
* @param db SQLiteDatabase
*/
public static void onDelete(final SQLiteDatabase db) {
db.execSQL(DROP_TABLE_STATEMENT);
onCreate(db);
}
/**
* This method is called on migrating from a older version to a newer version
* @param db SQLiteDatabase
* @param from Version from which we are migrating
* @param to Version to which we are migrating
*/
public static void onUpdate(final SQLiteDatabase db, int from, final int to) {
if (from == to) {
return;
}
if (from < 19) {
// doesn't exist yet
from++;
onUpdate(db, from, to);
return;
}
if (from == 19) {
// table added in version 20
onCreate(db);
from++;
onUpdate(db, from, to);
}
}
}
}

View file

@ -0,0 +1,216 @@
package fr.free.nrw.commons.recentlanguages
import android.annotation.SuppressLint
import android.content.ContentProviderClient
import android.content.ContentValues
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.os.RemoteException
import java.util.ArrayList
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Provider
import javax.inject.Singleton
/**
* Handles database operations for recently used languages
*/
@Singleton
class RecentLanguagesDao @Inject constructor(
@Named("recent_languages")
private val clientProvider: Provider<ContentProviderClient>
) {
/**
* Find all persisted recently used languages on database
* @return list of recently used languages
*/
fun getRecentLanguages(): List<Language> {
val languages = mutableListOf<Language>()
val db = clientProvider.get()
try {
db.query(
RecentLanguagesContentProvider.BASE_URI,
Table.ALL_FIELDS,
null,
arrayOf(),
null
)?.use { cursor ->
if (cursor.moveToLast()) {
do {
languages.add(fromCursor(cursor))
} while (cursor.moveToPrevious())
}
}
} catch (e: RemoteException) {
throw RuntimeException(e)
} finally {
db.release()
}
return languages
}
/**
* Add a Language to database
* @param language : Language to add
*/
fun addRecentLanguage(language: Language) {
val db = clientProvider.get()
try {
db.insert(
RecentLanguagesContentProvider.BASE_URI,
toContentValues(language)
)
} catch (e: RemoteException) {
throw RuntimeException(e)
} finally {
db.release()
}
}
/**
* Delete a language from database
* @param languageCode : code of the Language to delete
*/
fun deleteRecentLanguage(languageCode: String) {
val db = clientProvider.get()
try {
db.delete(
RecentLanguagesContentProvider.uriForCode(languageCode),
null,
null
)
} catch (e: RemoteException) {
throw RuntimeException(e)
} finally {
db.release()
}
}
/**
* Find a language from database based on its name
* @param languageCode : code of the Language to find
* @return boolean : is language in database ?
*/
fun findRecentLanguage(languageCode: String?): Boolean {
if (languageCode == null) { // Avoiding NPEs
return false
}
val db = clientProvider.get()
try {
db.query(
RecentLanguagesContentProvider.BASE_URI,
Table.ALL_FIELDS,
"${Table.COLUMN_CODE}=?",
arrayOf(languageCode),
null
)?.use { cursor ->
if (cursor.moveToFirst()) {
return true
}
}
} catch (e: RemoteException) {
throw RuntimeException(e)
} finally {
db.release()
}
return false
}
/**
* It creates an Recent Language object from data stored in the SQLite DB by using cursor
* @param cursor cursor
* @return Language object
*/
@SuppressLint("Range")
fun fromCursor(cursor: Cursor): Language {
// Hardcoding column positions!
val languageName = cursor.getString(
cursor.getColumnIndex(Table.COLUMN_NAME)
)
val languageCode = cursor.getString(
cursor.getColumnIndex(Table.COLUMN_CODE)
)
return Language(languageName, languageCode)
}
/**
* Takes data from Language and create a content value object
* @param recentLanguage recently used language
* @return ContentValues
*/
private fun toContentValues(recentLanguage: Language): ContentValues {
return ContentValues().apply {
put(Table.COLUMN_NAME, recentLanguage.languageName)
put(Table.COLUMN_CODE, recentLanguage.languageCode)
}
}
/**
* This class contains the database table architecture for recently used languages,
* It also contains queries and logic necessary to the create, update, delete this table.
*/
object Table {
const val TABLE_NAME = "recent_languages"
const val COLUMN_NAME = "language_name"
const val COLUMN_CODE = "language_code"
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
@JvmStatic
val ALL_FIELDS = arrayOf(
COLUMN_NAME,
COLUMN_CODE
)
private const val DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS $TABLE_NAME"
private const val CREATE_TABLE_STATEMENT = "CREATE TABLE $TABLE_NAME (" +
"$COLUMN_NAME STRING," +
"$COLUMN_CODE STRING PRIMARY KEY" +
");"
/**
* This method creates a LanguagesTable in SQLiteDatabase
* @param db SQLiteDatabase
*/
@SuppressLint("SQLiteString")
@JvmStatic
fun onCreate(db: SQLiteDatabase) {
db.execSQL(CREATE_TABLE_STATEMENT)
}
/**
* This method deletes LanguagesTable from SQLiteDatabase
* @param db SQLiteDatabase
*/
@JvmStatic
fun onDelete(db: SQLiteDatabase) {
db.execSQL(DROP_TABLE_STATEMENT)
onCreate(db)
}
/**
* This method is called on migrating from a older version to a newer version
* @param db SQLiteDatabase
* @param from Version from which we are migrating
* @param to Version to which we are migrating
*/
@JvmStatic
fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) {
if (from == to) {
return
}
if (from < 19) {
// doesn't exist yet
onUpdate(db, from + 1, to)
return
}
if (from == 19) {
// table added in version 20
onCreate(db)
onUpdate(db, from + 1, to)
}
}
}
}

View file

@ -1,423 +0,0 @@
package fr.free.nrw.commons.repository;
import androidx.annotation.Nullable;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.category.CategoriesModel;
import fr.free.nrw.commons.category.CategoryItem;
import fr.free.nrw.commons.contributions.Contribution;
import fr.free.nrw.commons.contributions.ContributionDao;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.nearby.NearbyPlaces;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.upload.ImageCoordinates;
import fr.free.nrw.commons.upload.SimilarImageInterface;
import fr.free.nrw.commons.upload.UploadController;
import fr.free.nrw.commons.upload.UploadItem;
import fr.free.nrw.commons.upload.UploadModel;
import fr.free.nrw.commons.upload.structure.depictions.DepictModel;
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.Single;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import timber.log.Timber;
/**
* The repository class for UploadActivity
*/
@Singleton
public class UploadRepository {
private final UploadModel uploadModel;
private final UploadController uploadController;
private final CategoriesModel categoriesModel;
private final NearbyPlaces nearbyPlaces;
private final DepictModel depictModel;
private static final double NEARBY_RADIUS_IN_KILO_METERS = 0.1; //100 meters
private final ContributionDao contributionDao;
@Inject
public UploadRepository(UploadModel uploadModel,
UploadController uploadController,
CategoriesModel categoriesModel,
NearbyPlaces nearbyPlaces,
DepictModel depictModel,
ContributionDao contributionDao) {
this.uploadModel = uploadModel;
this.uploadController = uploadController;
this.categoriesModel = categoriesModel;
this.nearbyPlaces = nearbyPlaces;
this.depictModel = depictModel;
this.contributionDao=contributionDao;
}
/**
* asks the RemoteDataSource to build contributions
*
* @return
*/
public Observable<Contribution> buildContributions() {
return uploadModel.buildContributions();
}
/**
* asks the RemoteDataSource to start upload for the contribution
*
* @param contribution
*/
public void prepareMedia(Contribution contribution) {
uploadController.prepareMedia(contribution);
}
public void saveContribution(Contribution contribution) {
contributionDao.save(contribution).blockingAwait();
}
/**
* Fetches and returns all the Upload Items
*
* @return
*/
public List<UploadItem> getUploads() {
return uploadModel.getUploads();
}
/**
*Prepare for a fresh upload
*/
public void cleanup() {
uploadModel.cleanUp();
//This needs further refactoring, this should not be here, right now the structure wont suppoort rhis
categoriesModel.cleanUp();
depictModel.cleanUp();
}
/**
* Fetches and returns the selected categories for the current upload
*
* @return
*/
public List<CategoryItem> getSelectedCategories() {
return categoriesModel.getSelectedCategories();
}
/**
* all categories from MWApi
*
* @param query
* @param imageTitleList
* @param selectedDepictions
* @return
*/
public Observable<List<CategoryItem>> searchAll(String query, List<String> imageTitleList,
List<DepictedItem> selectedDepictions) {
return categoriesModel.searchAll(query, imageTitleList, selectedDepictions);
}
/**
* sets the list of selected categories for the current upload
*
* @param categoryStringList
*/
public void setSelectedCategories(List<String> categoryStringList) {
uploadModel.setSelectedCategories(categoryStringList);
}
/**
* handles the category selection/deselection
*
* @param categoryItem
*/
public void onCategoryClicked(CategoryItem categoryItem, final Media media) {
categoriesModel.onCategoryItemClicked(categoryItem, media);
}
/**
* prunes the category list for irrelevant categories see #750
*
* @param name
* @return
*/
public boolean isSpammyCategory(String name) {
return categoriesModel.isSpammyCategory(name);
}
/**
* retursn the string list of available license from the LocalDataSource
*
* @return
*/
public List<String> getLicenses() {
return uploadModel.getLicenses();
}
/**
* returns the selected license for the current upload
*
* @return
*/
public String getSelectedLicense() {
return uploadModel.getSelectedLicense();
}
/**
* returns the number of Upload Items
*
* @return
*/
public int getCount() {
return uploadModel.getCount();
}
/**
* ask the RemoteDataSource to pre process the image
*
* @param uploadableFile
* @param place
* @param similarImageInterface
* @return
*/
public Observable<UploadItem> preProcessImage(UploadableFile uploadableFile, Place place,
SimilarImageInterface similarImageInterface, LatLng inAppPictureLocation) {
return uploadModel.preProcessImage(uploadableFile, place,
similarImageInterface, inAppPictureLocation);
}
/**
* query the RemoteDataSource for image quality
*
* @param uploadItem UploadItem whose caption is to be checked
* @return Quality of UploadItem
*/
public Single<Integer> getImageQuality(UploadItem uploadItem, LatLng location) {
return uploadModel.getImageQuality(uploadItem, location);
}
/**
* query the RemoteDataSource for image duplicity check
*
* @param filePath file to be checked
* @return IMAGE_DUPLICATE or IMAGE_OK
*/
public Single<Integer> checkDuplicateImage(String filePath) {
return uploadModel.checkDuplicateImage(filePath);
}
/**
* query the RemoteDataSource for caption quality
*
* @param uploadItem UploadItem whose caption is to be checked
* @return Quality of caption of the UploadItem
*/
public Single<Integer> getCaptionQuality(UploadItem uploadItem) {
return uploadModel.getCaptionQuality(uploadItem);
}
/**
* asks the LocalDataSource to delete the file with the given file path
*
* @param filePath
*/
public void deletePicture(String filePath) {
uploadModel.deletePicture(filePath);
}
/**
* fetches and returns the upload item
*
* @param index
* @return
*/
public UploadItem getUploadItem(int index) {
if (index >= 0) {
return uploadModel.getItems().get(index);
}
return null; //There is no item to copy details
}
/**
* set selected license for the current upload
*
* @param licenseName
*/
public void setSelectedLicense(String licenseName) {
uploadModel.setSelectedLicense(licenseName);
}
public void onDepictItemClicked(DepictedItem depictedItem, final Media media) {
uploadModel.onDepictItemClicked(depictedItem, media);
}
/**
* Fetches and returns the selected depictions for the current upload
*
* @return
*/
public List<DepictedItem> getSelectedDepictions() {
return uploadModel.getSelectedDepictions();
}
/**
* Provides selected existing depicts
*
* @return selected existing depicts
*/
public List<String> getSelectedExistingDepictions() {
return uploadModel.getSelectedExistingDepictions();
}
/**
* Initialize existing depicts
*
* @param selectedExistingDepictions existing depicts
*/
public void setSelectedExistingDepictions(final List<String> selectedExistingDepictions) {
uploadModel.setSelectedExistingDepictions(selectedExistingDepictions);
}
/**
* Search all depictions from
*
* @param query
* @return
*/
public Flowable<List<DepictedItem>> searchAllEntities(String query) {
return depictModel.searchAllEntities(query, this);
}
/**
* Gets the depiction for each unique {@link Place} associated with an {@link UploadItem}
* from {@link #getUploads()}
*
* @return a single that provides the depictions
*/
public Single<List<DepictedItem>> getPlaceDepictions() {
final Set<String> qids = new HashSet<>();
for (final UploadItem item : getUploads()) {
final Place place = item.getPlace();
if (place != null) {
qids.add(place.getWikiDataEntityId());
}
}
return depictModel.getPlaceDepictions(new ArrayList<>(qids));
}
/**
* Gets the category for each unique {@link Place} associated with an {@link UploadItem}
* from {@link #getUploads()}
*
* @return a single that provides the categories
*/
public Single<List<CategoryItem>> getPlaceCategories() {
final Set<String> qids = new HashSet<>();
for (final UploadItem item : getUploads()) {
final Place place = item.getPlace();
if (place != null) {
qids.add(place.getCategory());
}
}
return Single.fromObservable(categoriesModel.getCategoriesByName(new ArrayList<>(qids)));
}
/**
* Takes depict IDs as a parameter, converts into a slash separated String and Gets DepictItem
* from the server
*
* @param depictionsQIDs IDs of Depiction
* @return Flowable<List<DepictedItem>>
*/
public Flowable<List<DepictedItem>> getDepictions(final List<String> depictionsQIDs){
final String ids = joinQIDs(depictionsQIDs);
return depictModel.getDepictions(ids).toFlowable();
}
/**
* Builds a string by joining all IDs divided by "|"
*
* @param depictionsQIDs IDs of depiction ex. ["Q11023","Q1356"]
* @return string ex. "Q11023|Q1356"
*/
private String joinQIDs(final List<String> depictionsQIDs) {
if (depictionsQIDs != null && !depictionsQIDs.isEmpty()) {
final StringBuilder buffer = new StringBuilder(depictionsQIDs.get(0));
if (depictionsQIDs.size() > 1) {
for (int i = 1; i < depictionsQIDs.size(); i++) {
buffer.append("|");
buffer.append(depictionsQIDs.get(i));
}
}
return buffer.toString();
}
return null;
}
/**
* Returns nearest place matching the passed latitude and longitude
*
* @param decLatitude
* @param decLongitude
* @return
*/
@Nullable
public Place checkNearbyPlaces(final double decLatitude, final double decLongitude) {
try {
final List<Place> fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(new LatLng(
decLatitude, decLongitude, 0.0f),
Locale.getDefault().getLanguage(),
NEARBY_RADIUS_IN_KILO_METERS, null);
return (fromWikidataQuery != null && fromWikidataQuery.size() > 0) ? fromWikidataQuery
.get(0) : null;
} catch (final Exception e) {
Timber.e("Error fetching nearby places: %s", e.getMessage());
return null;
}
}
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
uploadModel.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex);
}
public boolean isWMLSupportedForThisPlace() {
return uploadModel.getItems().get(0).isWLMUpload();
}
/**
* Provides selected existing categories
*
* @return selected existing categories
*/
public List<String> getSelectedExistingCategories() {
return categoriesModel.getSelectedExistingCategories();
}
/**
* Initialize existing categories
*
* @param selectedExistingCategories existing categories
*/
public void setSelectedExistingCategories(final List<String> selectedExistingCategories) {
categoriesModel.setSelectedExistingCategories(selectedExistingCategories);
}
/**
* Takes category names and Gets CategoryItem from the server
*
* @param categories names of Category
* @return Observable<List<CategoryItem>>
*/
public Observable<List<CategoryItem>> getCategories(final List<String> categories){
return categoriesModel.getCategoriesByName(categories);
}
}

View file

@ -0,0 +1,410 @@
package fr.free.nrw.commons.repository
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.category.CategoriesModel
import fr.free.nrw.commons.category.CategoryItem
import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.filepicker.UploadableFile
import fr.free.nrw.commons.location.LatLng
import fr.free.nrw.commons.nearby.NearbyPlaces
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.upload.ImageCoordinates
import fr.free.nrw.commons.upload.SimilarImageInterface
import fr.free.nrw.commons.upload.UploadController
import fr.free.nrw.commons.upload.UploadItem
import fr.free.nrw.commons.upload.UploadModel
import fr.free.nrw.commons.upload.structure.depictions.DepictModel
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.Single
import java.util.Locale
import javax.inject.Inject
import javax.inject.Singleton
import timber.log.Timber
/**
* The repository class for UploadActivity
*/
@Singleton
class UploadRepository @Inject constructor(
private val uploadModel: UploadModel,
private val uploadController: UploadController,
private val categoriesModel: CategoriesModel,
private val nearbyPlaces: NearbyPlaces,
private val depictModel: DepictModel,
private val contributionDao: ContributionDao
) {
companion object {
private const val NEARBY_RADIUS_IN_KILO_METERS = 0.1 // 100 meters
}
/**
* Asks the RemoteDataSource to build contributions
*
* @return
*/
fun buildContributions(): Observable<Contribution> {
return uploadModel.buildContributions()
}
/**
* Asks the RemoteDataSource to start upload for the contribution
*
* @param contribution
*/
fun prepareMedia(contribution: Contribution) {
uploadController.prepareMedia(contribution)
}
fun saveContribution(contribution: Contribution) {
contributionDao.save(contribution).blockingAwait()
}
/**
* Fetches and returns all the Upload Items
*
* @return
*/
fun getUploads(): List<UploadItem> {
return uploadModel.getUploads()
}
/**
* Prepare for a fresh upload
*/
fun cleanup() {
uploadModel.cleanUp()
// This needs further refactoring, this should not be here, right now the structure
// won't support this
categoriesModel.cleanUp()
depictModel.cleanUp()
}
/**
* Fetches and returns the selected categories for the current upload
*
* @return
*/
fun getSelectedCategories(): List<CategoryItem> {
return categoriesModel.getSelectedCategories()
}
/**
* All categories from MWApi
*
* @param query
* @param imageTitleList
* @param selectedDepictions
* @return
*/
fun searchAll(
query: String,
imageTitleList: List<String>,
selectedDepictions: List<DepictedItem>
): Observable<List<CategoryItem>> {
return categoriesModel.searchAll(query, imageTitleList, selectedDepictions)
}
/**
* Sets the list of selected categories for the current upload
*
* @param categoryStringList
*/
fun setSelectedCategories(categoryStringList: List<String>) {
uploadModel.setSelectedCategories(categoryStringList)
}
/**
* Handles the category selection/deselection
*
* @param categoryItem
*/
fun onCategoryClicked(categoryItem: CategoryItem, media: Media?) {
categoriesModel.onCategoryItemClicked(categoryItem, media)
}
/**
* Prunes the category list for irrelevant categories see #750
*
* @param name
* @return
*/
fun isSpammyCategory(name: String): Boolean {
return categoriesModel.isSpammyCategory(name)
}
/**
* Returns the string list of available licenses from the LocalDataSource
*
* @return
*/
fun getLicenses(): List<String> {
return uploadModel.licenses
}
/**
* Returns the selected license for the current upload
*
* @return
*/
fun getSelectedLicense(): String {
return uploadModel.selectedLicense
}
/**
* Returns the number of Upload Items
*
* @return
*/
fun getCount(): Int {
return uploadModel.count
}
/**
* Ask the RemoteDataSource to preprocess the image
*
* @param uploadableFile
* @param place
* @param similarImageInterface
* @param inAppPictureLocation
* @return
*/
fun preProcessImage(
uploadableFile: UploadableFile,
place: Place?,
similarImageInterface: SimilarImageInterface,
inAppPictureLocation: LatLng?
): Observable<UploadItem> {
return uploadModel.preProcessImage(
uploadableFile,
place,
similarImageInterface,
inAppPictureLocation
)
}
/**
* Query the RemoteDataSource for image quality
*
* @param uploadItem UploadItem whose caption is to be checked
* @param location Location of the image
* @return Quality of UploadItem
*/
fun getImageQuality(uploadItem: UploadItem, location: LatLng?): Single<Int> {
return uploadModel.getImageQuality(uploadItem, location)
}
/**
* Query the RemoteDataSource for image duplicity check
*
* @param filePath file to be checked
* @return IMAGE_DUPLICATE or IMAGE_OK
*/
fun checkDuplicateImage(filePath: String): Single<Int> {
return uploadModel.checkDuplicateImage(filePath)
}
/**
* query the RemoteDataSource for caption quality
*
* @param uploadItem UploadItem whose caption is to be checked
* @return Quality of caption of the UploadItem
*/
fun getCaptionQuality(uploadItem: UploadItem): Single<Int> {
return uploadModel.getCaptionQuality(uploadItem)
}
/**
* asks the LocalDataSource to delete the file with the given file path
*
* @param filePath
*/
fun deletePicture(filePath: String) {
uploadModel.deletePicture(filePath)
}
/**
* fetches and returns the upload item
*
* @param index
* @return
*/
fun getUploadItem(index: Int): UploadItem? {
return if (index >= 0) {
uploadModel.items.getOrNull(index)
} else null //There is no item to copy details
}
/**
* set selected license for the current upload
*
* @param licenseName
*/
fun setSelectedLicense(licenseName: String) {
uploadModel.selectedLicense = licenseName
}
fun onDepictItemClicked(depictedItem: DepictedItem, media: Media?) {
uploadModel.onDepictItemClicked(depictedItem, media)
}
/**
* Fetches and returns the selected depictions for the current upload
*
* @return
*/
fun getSelectedDepictions(): List<DepictedItem> {
return uploadModel.selectedDepictions
}
/**
* Provides selected existing depicts
*
* @return selected existing depicts
*/
fun getSelectedExistingDepictions(): List<String> {
return uploadModel.selectedExistingDepictions
}
/**
* Initialize existing depicts
*
* @param selectedExistingDepictions existing depicts
*/
fun setSelectedExistingDepictions(selectedExistingDepictions: List<String>) {
uploadModel.selectedExistingDepictions = selectedExistingDepictions
}
/**
* Search all depictions from
*
* @param query
* @return
*/
fun searchAllEntities(query: String): Flowable<List<DepictedItem>> {
return depictModel.searchAllEntities(query, this)
}
/**
* Gets the depiction for each unique {@link Place} associated with an {@link UploadItem}
* from {@link #getUploads()}
*
* @return a single that provides the depictions
*/
fun getPlaceDepictions(): Single<List<DepictedItem>> {
val qids = mutableSetOf<String>()
getUploads().forEach { item ->
item.place?.let {
it.wikiDataEntityId?.let { it1 ->
qids.add(it1)
}
}
}
return depictModel.getPlaceDepictions(qids.toList())
}
/**
* Gets the category for each unique {@link Place} associated with an {@link UploadItem}
* from {@link #getUploads()}
*
* @return a single that provides the categories
*/
fun getPlaceCategories(): Single<List<CategoryItem>> {
val qids = mutableSetOf<String>()
getUploads().forEach { item ->
item.place?.category?.let { qids.add(it) }
}
return Single.fromObservable(categoriesModel.getCategoriesByName(qids.toList()))
}
/**
* Takes depict IDs as a parameter, converts into a slash separated String and Gets DepictItem
* from the server
*
* @param depictionsQIDs IDs of Depiction
* @return Flowable<List<DepictedItem>>
*/
fun getDepictions(depictionsQIDs: List<String>): Flowable<List<DepictedItem>> {
val ids = joinQIDs(depictionsQIDs) ?: ""
return depictModel.getDepictions(ids).toFlowable()
}
/**
* Builds a string by joining all IDs divided by "|"
*
* @param depictionsQIDs IDs of depiction ex. ["Q11023","Q1356"]
* @return string ex. "Q11023|Q1356"
*/
private fun joinQIDs(depictionsQIDs: List<String>?): String? {
return depictionsQIDs?.takeIf {
it.isNotEmpty()
}?.joinToString("|")
}
/**
* Returns nearest place matching the passed latitude and longitude
*
* @param decLatitude
* @param decLongitude
* @return
*/
fun checkNearbyPlaces(decLatitude: Double, decLongitude: Double): Place? {
return try {
val fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(
LatLng(decLatitude, decLongitude, 0.0f),
Locale.getDefault().language,
NEARBY_RADIUS_IN_KILO_METERS,
null
)
fromWikidataQuery?.firstOrNull()
} catch (e: Exception) {
Timber.e("Error fetching nearby places: %s", e.message)
null
}
}
fun useSimilarPictureCoordinates(imageCoordinates: ImageCoordinates, uploadItemIndex: Int) {
uploadModel.useSimilarPictureCoordinates(
imageCoordinates,
uploadItemIndex
)
}
fun isWMLSupportedForThisPlace(): Boolean {
return uploadModel.items.firstOrNull()?.isWLMUpload == true
}
/**
* Provides selected existing categories
*
* @return selected existing categories
*/
fun getSelectedExistingCategories(): List<String> {
return categoriesModel.getSelectedExistingCategories()
}
/**
* Initialize existing categories
*
* @param selectedExistingCategories existing categories
*/
fun setSelectedExistingCategories(selectedExistingCategories: List<String>) {
categoriesModel.setSelectedExistingCategories(
selectedExistingCategories.toMutableList()
)
}
/**
* Takes category names and Gets CategoryItem from the server
*
* @param categories names of Category
* @return Observable<List<CategoryItem>>
*/
fun getCategories(categories: List<String>): Observable<List<CategoryItem>> {
return categoriesModel.getCategoriesByName(categories)
?.map { it.toList() } ?: Observable.empty()
}
}

View file

@ -61,7 +61,7 @@ class CategoriesPresenter
.doOnNext {
view.showProgress(true)
}.switchMap(::searchResults)
.map { repository.selectedCategories + it }
.map { repository.getSelectedCategories() + it }
.map { it.distinctBy { categoryItem -> categoryItem.name } }
.observeOn(mainThreadScheduler)
.subscribe(
@ -89,7 +89,7 @@ class CategoriesPresenter
private fun searchResults(term: String): Observable<List<CategoryItem>>? {
if (media == null) {
return repository
.searchAll(term, getImageTitleList(), repository.selectedDepictions)
.searchAll(term, getImageTitleList(), repository.getSelectedDepictions())
.subscribeOn(ioScheduler)
.map {
it.filter { categoryItem ->
@ -101,13 +101,13 @@ class CategoriesPresenter
return Observable
.zip(
repository
.getCategories(repository.selectedExistingCategories)
.getCategories(repository.getSelectedExistingCategories())
.map { list ->
list.map {
CategoryItem(it.name, it.description, it.thumbnail, true)
}
},
repository.searchAll(term, getImageTitleList(), repository.selectedDepictions),
repository.searchAll(term, getImageTitleList(), repository.getSelectedDepictions()),
) { it1, it2 ->
it1 + it2
}.subscribeOn(ioScheduler)
@ -138,7 +138,7 @@ class CategoriesPresenter
* @return
*/
private fun getImageTitleList(): List<String> =
repository.uploads
repository.getUploads()
.map { it.uploadMediaDetails[0].captionText }
.filterNot { TextUtils.isEmpty(it) }
@ -146,7 +146,7 @@ class CategoriesPresenter
* Verifies the number of categories selected, prompts the user if none selected
*/
override fun verifyCategories() {
val selectedCategories = repository.selectedCategories
val selectedCategories = repository.getSelectedCategories()
if (selectedCategories.isNotEmpty()) {
repository.setSelectedCategories(selectedCategories.map { it.name })
view.goToNextScreen()
@ -173,14 +173,14 @@ class CategoriesPresenter
) {
this.view = view
this.media = media
repository.selectedExistingCategories = view.existingCategories
repository.setSelectedExistingCategories(view.existingCategories)
compositeDisposable.add(
searchTerms
.observeOn(mainThreadScheduler)
.doOnNext {
view.showProgress(true)
}.switchMap(::searchResults)
.map { repository.selectedCategories + it }
.map { repository.getSelectedCategories() + it }
.map { it.distinctBy { categoryItem -> categoryItem.name } }
.observeOn(mainThreadScheduler)
.subscribe(
@ -218,13 +218,21 @@ class CategoriesPresenter
wikiText: String,
) {
// check if view.existingCategories is null
if (repository.selectedCategories.isNotEmpty() ||
(view.existingCategories != null && repository.selectedExistingCategories.size != view.existingCategories.size)
if (
repository.getSelectedCategories().isNotEmpty()
||
(
view.existingCategories != null
&&
repository.getSelectedExistingCategories().size
!=
view.existingCategories.size
)
) {
val selectedCategories: MutableList<String> =
(
repository.selectedCategories.map { it.name }.toMutableList() +
repository.selectedExistingCategories
repository.getSelectedCategories().map { it.name }.toMutableList() +
repository.getSelectedExistingCategories()
).toMutableList()
if (selectedCategories.isNotEmpty()) {
@ -305,7 +313,7 @@ class CategoriesPresenter
override fun selectCategories() {
compositeDisposable.add(
repository.placeCategories
repository.getPlaceCategories()
.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)
.subscribe(::selectNewCategories),

View file

@ -93,14 +93,14 @@ class DepictsPresenter
return repository
.searchAllEntities(querystring)
.subscribeOn(ioScheduler)
.map { repository.selectedDepictions + it + recentDepictedItemList + controller.loadFavoritesItems() }
.map { repository.getSelectedDepictions() + it + recentDepictedItemList + controller.loadFavoritesItems() }
.map { it.filterNot { item -> WikidataDisambiguationItems.isDisambiguationItem(item.instanceOfs) } }
.map { it.distinctBy(DepictedItem::id) }
} else {
return Flowable
.zip(
repository
.getDepictions(repository.selectedExistingDepictions)
.getDepictions(repository.getSelectedExistingDepictions())
.map { list ->
list.map {
DepictedItem(
@ -118,7 +118,7 @@ class DepictsPresenter
) { it1, it2 ->
it1 + it2
}.subscribeOn(ioScheduler)
.map { repository.selectedDepictions + it + recentDepictedItemList + controller.loadFavoritesItems() }
.map { repository.getSelectedDepictions() + it + recentDepictedItemList + controller.loadFavoritesItems() }
.map { it.filterNot { item -> WikidataDisambiguationItems.isDisambiguationItem(item.instanceOfs) } }
.map { it.distinctBy(DepictedItem::id) }
}
@ -135,7 +135,7 @@ class DepictsPresenter
*/
override fun selectPlaceDepictions() {
compositeDisposable.add(
repository.placeDepictions
repository.getPlaceDepictions()
.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)
.subscribe(::selectNewDepictions),
@ -188,10 +188,10 @@ class DepictsPresenter
* from the depiction list
*/
override fun verifyDepictions() {
if (repository.selectedDepictions.isNotEmpty()) {
if (repository.getSelectedDepictions().isNotEmpty()) {
if (::depictsDao.isInitialized) {
// save all the selected Depicted item in room Database
depictsDao.savingDepictsInRoomDataBase(repository.selectedDepictions)
depictsDao.savingDepictsInRoomDataBase(repository.getSelectedDepictions())
}
view.goToNextScreen()
} else {
@ -205,20 +205,20 @@ class DepictsPresenter
*/
@SuppressLint("CheckResult")
override fun updateDepictions(media: Media) {
if (repository.selectedDepictions.isNotEmpty() ||
repository.selectedExistingDepictions.size != view.existingDepictions.size
if (repository.getSelectedDepictions().isNotEmpty() ||
repository.getSelectedExistingDepictions().size != view.existingDepictions.size
) {
view.showProgressDialog()
val selectedDepictions: MutableList<String> =
(
repository.selectedDepictions.map { it.id }.toMutableList() +
repository.selectedExistingDepictions
repository.getSelectedDepictions().map { it.id }.toMutableList() +
repository.getSelectedExistingDepictions()
).toMutableList()
if (selectedDepictions.isNotEmpty()) {
if (::depictsDao.isInitialized) {
// save all the selected Depicted item in room Database
depictsDao.savingDepictsInRoomDataBase(repository.selectedDepictions)
depictsDao.savingDepictsInRoomDataBase(repository.getSelectedDepictions())
}
compositeDisposable.add(
@ -254,7 +254,7 @@ class DepictsPresenter
) {
this.view = view
this.media = media
repository.selectedExistingDepictions = view.existingDepictions
repository.setSelectedExistingDepictions(view.existingDepictions)
compositeDisposable.add(
searchTerm
.observeOn(mainThreadScheduler)

View file

@ -39,7 +39,7 @@ class DepictModel
for (place in places) {
place.wikiDataEntityId?.let { qids.add(it) }
}
repository.uploads.forEach { item ->
repository.getUploads().forEach { item ->
if (item.gpsCoords != null && item.gpsCoords.imageCoordsExists) {
Coordinates2Country
.countryQID(

View file

@ -56,9 +56,9 @@ class CategoriesPresenterTest {
@Throws(Exception::class)
fun `Test onAttachViewWithMedia when media is not null`() {
categoriesPresenter.onAttachViewWithMedia(view, media())
whenever(repository.getCategories(repository.selectedExistingCategories))
whenever(repository.getCategories(repository.getSelectedExistingCategories()))
.thenReturn(Observable.just(mutableListOf(categoryItem())))
whenever(repository.searchAll("mock", emptyList(), repository.selectedDepictions))
whenever(repository.searchAll("mock", emptyList(), repository.getSelectedDepictions()))
.thenReturn(Observable.just(mutableListOf(categoryItem())))
val method: Method =
CategoriesPresenter::class.java.getDeclaredMethod(
@ -88,7 +88,7 @@ class CategoriesPresenterTest {
val emptyCaptionUploadItem = mock<UploadItem>()
whenever(emptyCaptionUploadItem.uploadMediaDetails)
.thenReturn(listOf(UploadMediaDetail(captionText = "")))
whenever(repository.uploads).thenReturn(
whenever(repository.getUploads()).thenReturn(
listOf(
nonEmptyCaptionUploadItem,
emptyCaptionUploadItem,
@ -105,7 +105,7 @@ class CategoriesPresenterTest {
)
whenever(repository.isSpammyCategory("selected")).thenReturn(false)
whenever(repository.isSpammyCategory("doesContainYear")).thenReturn(true)
whenever(repository.selectedCategories).thenReturn(
whenever(repository.getSelectedCategories()).thenReturn(
listOf(
categoryItem("selected", "", "", true),
),
@ -130,7 +130,7 @@ class CategoriesPresenterTest {
whenever(repository.searchAll(any(), any(), any()))
.thenReturn(Observable.just(emptyCategories))
whenever(repository.selectedCategories).thenReturn(listOf())
whenever(repository.getSelectedCategories()).thenReturn(listOf())
categoriesPresenter.searchForCategories(query)
testScheduler.triggerActions()
val method: Method =
@ -154,7 +154,7 @@ class CategoriesPresenterTest {
fun `verifyCategories with non empty selection goes to next screen`() {
categoriesPresenter.onAttachView(view)
val item = categoryItem()
whenever(repository.selectedCategories).thenReturn(listOf(item))
whenever(repository.getSelectedCategories()).thenReturn(listOf(item))
categoriesPresenter.verifyCategories()
verify(repository).setSelectedCategories(listOf(item.name))
verify(view).goToNextScreen()
@ -163,7 +163,7 @@ class CategoriesPresenterTest {
@Test
fun `verifyCategories with empty selection show no category selected`() {
categoriesPresenter.onAttachView(view)
whenever(repository.selectedCategories).thenReturn(listOf())
whenever(repository.getSelectedCategories()).thenReturn(listOf())
categoriesPresenter.verifyCategories()
verify(view).showNoCategorySelected()
}

View file

@ -74,7 +74,7 @@ class DepictsPresenterTest {
)
whenever(repository.searchAllEntities("")).thenReturn(Flowable.just(searchResults))
val selectedItem = depictedItem(id = "selected")
whenever(repository.selectedDepictions).thenReturn(listOf(selectedItem))
whenever(repository.getSelectedDepictions()).thenReturn(listOf(selectedItem))
depictsPresenter.searchForDepictions("")
testScheduler.triggerActions()
verify(view).showProgress(false)
@ -123,14 +123,14 @@ class DepictsPresenterTest {
@Test
fun `verifyDepictions with non empty selectedDepictions goes to next screen`() {
whenever(repository.selectedDepictions).thenReturn(listOf(depictedItem()))
whenever(repository.getSelectedDepictions()).thenReturn(listOf(depictedItem()))
depictsPresenter.verifyDepictions()
verify(view).goToNextScreen()
}
@Test
fun `verifyDepictions with empty selectedDepictions goes to noDepictionSelected`() {
whenever(repository.selectedDepictions).thenReturn(emptyList())
whenever(repository.getSelectedDepictions()).thenReturn(emptyList())
depictsPresenter.verifyDepictions()
verify(view).noDepictionSelected()
}
@ -162,7 +162,7 @@ class DepictsPresenterTest {
@Test
fun `Test searchResults when media is not null`() {
Whitebox.setInternalState(depictsPresenter, "media", media)
whenever(repository.getDepictions(repository.selectedExistingDepictions))
whenever(repository.getDepictions(repository.getSelectedExistingDepictions()))
.thenReturn(Flowable.just(listOf(depictedItem())))
whenever(repository.searchAllEntities("querystring"))
.thenReturn(Flowable.just(listOf(depictedItem())))

View file

@ -84,7 +84,7 @@ class UploadPresenterTest {
fun handleSubmitImagesNoLocationWithConsecutiveNoLocationUploads() {
`when`(imageCoords.imageCoordsExists).thenReturn(false)
`when`(uploadItem.getGpsCoords()).thenReturn(imageCoords)
`when`(repository.uploads).thenReturn(uploadableItems)
`when`(repository.getUploads()).thenReturn(uploadableItems)
uploadableItems.add(uploadItem)
// test 1 - insufficient count
@ -112,7 +112,7 @@ class UploadPresenterTest {
).thenReturn(UploadPresenter.CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES_REMINDER_THRESHOLD)
`when`(imageCoords.imageCoordsExists).thenReturn(true)
`when`(uploadItem.getGpsCoords()).thenReturn(imageCoords)
`when`(repository.uploads).thenReturn(uploadableItems)
`when`(repository.getUploads()).thenReturn(uploadableItems)
uploadableItems.add(uploadItem)
uploadPresenter.handleSubmit()
// no alert dialog expected

View file

@ -117,7 +117,7 @@ class UploadRepositoryUnitTest {
@Test
fun testGetUploads() {
assertEquals(repository.uploads, uploadModel.uploads)
assertEquals(repository.getUploads(), uploadModel.uploads)
}
@Test
@ -130,7 +130,7 @@ class UploadRepositoryUnitTest {
@Test
fun testGetSelectedCategories() {
assertEquals(repository.selectedCategories, categoriesModel.getSelectedCategories())
assertEquals(repository.getSelectedCategories(), categoriesModel.getSelectedCategories())
}
@Test
@ -163,17 +163,17 @@ class UploadRepositoryUnitTest {
@Test
fun testGetLicenses() {
assertEquals(repository.licenses, uploadModel.licenses)
assertEquals(repository.getLicenses(), uploadModel.licenses)
}
@Test
fun testGetSelectedLicense() {
assertEquals(repository.selectedLicense, uploadModel.selectedLicense)
assertEquals(repository.getSelectedLicense(), uploadModel.selectedLicense)
}
@Test
fun testGetCount() {
assertEquals(repository.count, uploadModel.count)
assertEquals(repository.getCount(), uploadModel.count)
}
@Test
@ -242,12 +242,12 @@ class UploadRepositoryUnitTest {
@Test
fun testGetSelectedDepictions() {
assertEquals(repository.selectedDepictions, uploadModel.selectedDepictions)
assertEquals(repository.getSelectedDepictions(), uploadModel.selectedDepictions)
}
@Test
fun testGetSelectedExistingDepictions() {
assertEquals(repository.selectedExistingDepictions, uploadModel.selectedExistingDepictions)
assertEquals(repository.getSelectedExistingDepictions(), uploadModel.selectedExistingDepictions)
}
@Test
@ -264,7 +264,7 @@ class UploadRepositoryUnitTest {
`when`(uploadItem.place).thenReturn(place)
`when`(place.wikiDataEntityId).thenReturn("1")
assertEquals(
repository.placeDepictions,
repository.getPlaceDepictions(),
depictModel.getPlaceDepictions(listOf("1")),
)
}
@ -326,7 +326,7 @@ class UploadRepositoryUnitTest {
`when`(uploadModel.items).thenReturn(listOf(uploadItem))
`when`(uploadItem.isWLMUpload).thenReturn(true)
assertEquals(
repository.isWMLSupportedForThisPlace,
repository.isWMLSupportedForThisPlace(),
true,
)
}
@ -369,7 +369,7 @@ class UploadRepositoryUnitTest {
@Test
fun testGetSelectedExistingCategories() {
assertEquals(
repository.selectedExistingCategories,
repository.getSelectedExistingCategories(),
categoriesModel.getSelectedExistingCategories(),
)
}