mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
* #3813 Convert MediaClient to Kotlin - convert * #3813 Convert MediaClient to Kotlin - update tests * #3813 Convert MediaClient to Kotlin - fix List typing * #3813 Convert MediaClient to Kotlin - fix mock injecting
This commit is contained in:
parent
e3213aa5bd
commit
422890cac4
7 changed files with 319 additions and 302 deletions
|
|
@ -8,7 +8,6 @@ import fr.free.nrw.commons.media.MediaClient
|
|||
import io.reactivex.Scheduler
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
|
@ -52,11 +51,11 @@ class ContributionBoundaryCallback @Inject constructor(
|
|||
* Fetches contributions using the MediaWiki API
|
||||
*/
|
||||
fun fetchContributions() {
|
||||
if (mediaClient.doesMediaListForUserHaveMorePages(sessionManager.userName).not()) {
|
||||
if (mediaClient.doesMediaListForUserHaveMorePages(sessionManager.userName!!).not()) {
|
||||
return
|
||||
}
|
||||
compositeDisposable.add(
|
||||
mediaClient.getMediaListForUser(sessionManager.userName)
|
||||
mediaClient.getMediaListForUser(sessionManager.userName!!)
|
||||
.map { mediaList: List<Media?> ->
|
||||
mediaList.map {
|
||||
Contribution(it, Contribution.STATE_COMPLETED)
|
||||
|
|
@ -86,4 +85,4 @@ class ContributionBoundaryCallback @Inject constructor(
|
|||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import fr.free.nrw.commons.explore.LiveDataConverter
|
|||
import fr.free.nrw.commons.explore.PageableDataSource
|
||||
import fr.free.nrw.commons.explore.depictions.LoadFunction
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import fr.free.nrw.commons.media.MediaClient.NO_CAPTION
|
||||
import fr.free.nrw.commons.media.MediaClient.Companion.NO_CAPTION
|
||||
import javax.inject.Inject
|
||||
|
||||
class PageableMediaDataSource @Inject constructor(
|
||||
|
|
|
|||
|
|
@ -1,277 +0,0 @@
|
|||
package fr.free.nrw.commons.media;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.utils.CommonsDateUtil;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
|
||||
import org.wikipedia.wikidata.Entities;
|
||||
import org.wikipedia.wikidata.Entities.Entity;
|
||||
import org.wikipedia.wikidata.Entities.Label;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Media Client to handle custom calls to Commons MediaWiki APIs
|
||||
*/
|
||||
@Singleton
|
||||
public class MediaClient {
|
||||
|
||||
private final MediaInterface mediaInterface;
|
||||
private final PageMediaInterface pageMediaInterface;
|
||||
private final MediaDetailInterface mediaDetailInterface;
|
||||
|
||||
//OkHttpJsonApiClient used JsonKvStore for this. I don't know why.
|
||||
private Map<String, Map<String, String>> continuationStore;
|
||||
private Map<String, Boolean> continuationExists;
|
||||
public static final String NO_CAPTION = "No caption";
|
||||
private static final String NO_DEPICTION = "No depiction";
|
||||
|
||||
@Inject
|
||||
public MediaClient(MediaInterface mediaInterface,
|
||||
PageMediaInterface pageMediaInterface,
|
||||
MediaDetailInterface mediaDetailInterface) {
|
||||
this.mediaInterface = mediaInterface;
|
||||
this.pageMediaInterface = pageMediaInterface;
|
||||
this.mediaDetailInterface = mediaDetailInterface;
|
||||
this.continuationStore = new HashMap<>();
|
||||
this.continuationExists = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a page exists on Commons
|
||||
* The same method can be used to check for file or talk page
|
||||
*
|
||||
* @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg
|
||||
*/
|
||||
public Single<Boolean> checkPageExistsUsingTitle(String title) {
|
||||
return mediaInterface.checkPageExistsUsingTitle(title)
|
||||
.map(mwQueryResponse -> mwQueryResponse
|
||||
.query().firstPage().pageId() > 0)
|
||||
.singleOrError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the fileSha and returns whether a file with a matching SHA exists or not
|
||||
*
|
||||
* @param fileSha SHA of the file to be checked
|
||||
*/
|
||||
public Single<Boolean> checkFileExistsUsingSha(String fileSha) {
|
||||
return mediaInterface.checkFileExistsUsingSha(fileSha)
|
||||
.map(mwQueryResponse -> mwQueryResponse
|
||||
.query().allImages().size() > 0)
|
||||
.singleOrError();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the category as input and returns a list of Media objects filtered using image generator query
|
||||
* It uses the generator query API to get the images searched using a query, 10 at a time.
|
||||
*
|
||||
* @param category the search category. Must start with "Category:"
|
||||
* @return
|
||||
*/
|
||||
public Single<List<Media>> getMediaListFromCategory(String category) {
|
||||
return responseToMediaList(
|
||||
continuationStore.containsKey("category_" + category) ?
|
||||
mediaInterface.getMediaListFromCategory(category, 10, continuationStore.get("category_" + category)) : //if true
|
||||
mediaInterface.getMediaListFromCategory(category, 10, Collections.emptyMap()),
|
||||
"category_" + category); //if false
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the userName as input and returns a list of Media objects filtered using
|
||||
* allimages query It uses the allimages query API to get the images contributed by the userName,
|
||||
* 10 at a time.
|
||||
*
|
||||
* @param userName the username
|
||||
* @return
|
||||
*/
|
||||
public Single<List<Media>> getMediaListForUser(String userName) {
|
||||
Map<String, String> continuation =
|
||||
continuationStore.containsKey("user_" + userName)
|
||||
? continuationStore.get("user_" + userName)
|
||||
: Collections.emptyMap();
|
||||
return responseToMediaList(mediaInterface
|
||||
.getMediaListForUser(userName, 10, continuation), "user_" + userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if media for user has reached the end of the list.
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean doesMediaListForUserHaveMorePages(String userName) {
|
||||
final String key = "user_" + userName;
|
||||
if(continuationExists.containsKey(key)) {
|
||||
return continuationExists.get(key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes a keyword as input and returns a list of Media objects filtered using image generator query
|
||||
* It uses the generator query API to get the images searched using a query, 10 at a time.
|
||||
*
|
||||
* @param keyword the search keyword
|
||||
* @param limit
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
public Single<MwQueryResponse> getMediaListFromSearch(String keyword, int limit, int offset) {
|
||||
return mediaInterface.getMediaListFromSearch(keyword, limit, offset);
|
||||
|
||||
}
|
||||
|
||||
private Single<List<Media>> responseToMediaList(Observable<MwQueryResponse> response, String key) {
|
||||
return response.flatMap(mwQueryResponse -> {
|
||||
if (null == mwQueryResponse
|
||||
|| null == mwQueryResponse.query()
|
||||
|| null == mwQueryResponse.query().pages()) {
|
||||
return Observable.empty();
|
||||
}
|
||||
if(mwQueryResponse.continuation() != null) {
|
||||
continuationStore.put(key, mwQueryResponse.continuation());
|
||||
continuationExists.put(key, true);
|
||||
} else {
|
||||
continuationExists.put(key, false);
|
||||
}
|
||||
return Observable.fromIterable(mwQueryResponse.query().pages());
|
||||
})
|
||||
.map(Media::from)
|
||||
.collect(ArrayList<Media>::new, List::add);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Media object from the imageInfo API
|
||||
*
|
||||
* @param titles the tiles to be searched for. Can be filename or template name
|
||||
* @return
|
||||
*/
|
||||
public Single<Media> getMedia(String titles) {
|
||||
return mediaInterface.getMedia(titles)
|
||||
.flatMap(mwQueryResponse -> {
|
||||
if (null == mwQueryResponse
|
||||
|| null == mwQueryResponse.query()
|
||||
|| null == mwQueryResponse.query().firstPage()) {
|
||||
return Observable.empty();
|
||||
}
|
||||
return Observable.just(mwQueryResponse.query().firstPage());
|
||||
})
|
||||
.map(Media::from)
|
||||
.single(Media.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method returns the picture of the day
|
||||
*
|
||||
* @return Media object corresponding to the picture of the day
|
||||
*/
|
||||
@NonNull
|
||||
public Single<Media> getPictureOfTheDay() {
|
||||
String date = CommonsDateUtil.getIso8601DateFormatShort().format(new Date());
|
||||
Timber.d("Current date is %s", date);
|
||||
String template = "Template:Potd/" + date;
|
||||
return mediaInterface.getMediaWithGenerator(template)
|
||||
.flatMap(mwQueryResponse -> {
|
||||
if (null == mwQueryResponse
|
||||
|| null == mwQueryResponse.query()
|
||||
|| null == mwQueryResponse.query().firstPage()) {
|
||||
return Observable.empty();
|
||||
}
|
||||
return Observable.just(mwQueryResponse.query().firstPage());
|
||||
})
|
||||
.map(Media::from)
|
||||
.single(Media.EMPTY);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public Single<String> getPageHtml(String title){
|
||||
return mediaInterface.getPageHtml(title)
|
||||
.filter(MwParseResponse::success)
|
||||
.map(MwParseResponse::parse)
|
||||
.map(MwParseResult::text)
|
||||
.first("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return caption for image using wikibaseIdentifier
|
||||
*/
|
||||
public Single<String> getCaptionByWikibaseIdentifier(String wikibaseIdentifier) {
|
||||
return mediaDetailInterface.getEntityForImage(Locale.getDefault().getLanguage(), wikibaseIdentifier)
|
||||
.map(mediaDetailResponse -> {
|
||||
if (isSuccess(mediaDetailResponse)) {
|
||||
for (Entity wikibaseItem : mediaDetailResponse.entities().values()) {
|
||||
for (Label label : wikibaseItem.labels().values()) {
|
||||
return label.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO_CAPTION;
|
||||
})
|
||||
.singleOrError();
|
||||
}
|
||||
|
||||
public Single<Boolean> doesPageContainMedia(String title) {
|
||||
return pageMediaInterface.getMediaList(title)
|
||||
.map(pageMediaListResponse -> {
|
||||
return pageMediaListResponse.getItems().size() > 0;
|
||||
}).singleOrError();
|
||||
}
|
||||
|
||||
private boolean isSuccess(Entities response) {
|
||||
return response != null && response.getSuccess() == 1 && response.entities() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Structured data from API
|
||||
*
|
||||
* @param filename
|
||||
* @return a map containing caption and depictions (empty string in the map if no caption/depictions)
|
||||
*/
|
||||
public Single<Depictions> getDepictions(String filename) {
|
||||
return mediaDetailInterface.fetchEntitiesByFileName(Locale.getDefault().getLanguage(), filename)
|
||||
.map(entities -> Depictions.from(entities, this))
|
||||
.singleOrError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets labels for Depictions using Entity Id from MediaWikiAPI
|
||||
*
|
||||
* @param entityId EntityId (Ex: Q81566) of the depict entity
|
||||
* @return label
|
||||
*/
|
||||
public Single<String> getLabelForDepiction(String entityId, String language) {
|
||||
return mediaDetailInterface.getEntity(entityId)
|
||||
.map(entities -> {
|
||||
if (isSuccess(entities)) {
|
||||
for (Entity entity : entities.entities().values()) {
|
||||
final Map<String, Label> languageToLabelMap = entity.labels();
|
||||
if (languageToLabelMap.containsKey(language)) {
|
||||
return languageToLabelMap.get(language).value();
|
||||
}
|
||||
for (Label label : languageToLabelMap.values()) {
|
||||
return label.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("failed getEntities");
|
||||
});
|
||||
}
|
||||
|
||||
public Single<Entities> getEntities(String entityId) {
|
||||
return mediaDetailInterface.getEntity(entityId);
|
||||
}
|
||||
}
|
||||
300
app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
Normal file
300
app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
package fr.free.nrw.commons.media
|
||||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.media.Depictions.Companion.from
|
||||
import fr.free.nrw.commons.utils.CommonsDateUtil
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryPage
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryResponse
|
||||
import org.wikipedia.wikidata.Entities
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/**
|
||||
* Media Client to handle custom calls to Commons MediaWiki APIs
|
||||
*/
|
||||
@Singleton
|
||||
class MediaClient @Inject constructor(
|
||||
private val mediaInterface: MediaInterface,
|
||||
private val pageMediaInterface: PageMediaInterface,
|
||||
private val mediaDetailInterface: MediaDetailInterface
|
||||
) {
|
||||
|
||||
//OkHttpJsonApiClient used JsonKvStore for this. I don't know why.
|
||||
private val continuationStore: MutableMap<String, Map<String, String>?>
|
||||
private val continuationExists: MutableMap<String, Boolean>
|
||||
|
||||
/**
|
||||
* Checks if a page exists on Commons
|
||||
* The same method can be used to check for file or talk page
|
||||
*
|
||||
* @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg
|
||||
*/
|
||||
fun checkPageExistsUsingTitle(title: String?): Single<Boolean> {
|
||||
return mediaInterface.checkPageExistsUsingTitle(title)
|
||||
.map { mwQueryResponse: MwQueryResponse ->
|
||||
mwQueryResponse
|
||||
.query()!!.firstPage()!!.pageId() > 0
|
||||
}
|
||||
.singleOrError()
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the fileSha and returns whether a file with a matching SHA exists or not
|
||||
*
|
||||
* @param fileSha SHA of the file to be checked
|
||||
*/
|
||||
fun checkFileExistsUsingSha(fileSha: String?): Single<Boolean> {
|
||||
return mediaInterface.checkFileExistsUsingSha(fileSha)
|
||||
.map { mwQueryResponse: MwQueryResponse ->
|
||||
mwQueryResponse
|
||||
.query()!!.allImages().size > 0
|
||||
}
|
||||
.singleOrError()
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the category as input and returns a list of Media objects filtered using image generator query
|
||||
* It uses the generator query API to get the images searched using a query, 10 at a time.
|
||||
*
|
||||
* @param category the search category. Must start with "Category:"
|
||||
* @return
|
||||
*/
|
||||
fun getMediaListFromCategory(category: String): Single<List<Media>> {
|
||||
return responseToMediaList(
|
||||
if (continuationStore.containsKey("category_$category")) mediaInterface.getMediaListFromCategory(
|
||||
category,
|
||||
10,
|
||||
continuationStore["category_$category"]
|
||||
) else //if true
|
||||
mediaInterface.getMediaListFromCategory(
|
||||
category,
|
||||
10,
|
||||
emptyMap()
|
||||
),
|
||||
"category_$category"
|
||||
) //if false
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the userName as input and returns a list of Media objects filtered using
|
||||
* allimages query It uses the allimages query API to get the images contributed by the userName,
|
||||
* 10 at a time.
|
||||
*
|
||||
* @param userName the username
|
||||
* @return
|
||||
*/
|
||||
fun getMediaListForUser(userName: String): Single<List<Media>> {
|
||||
val continuation =
|
||||
if (continuationStore.containsKey("user_$userName")) continuationStore["user_$userName"] else emptyMap()
|
||||
return responseToMediaList(
|
||||
mediaInterface
|
||||
.getMediaListForUser(userName, 10, continuation), "user_$userName"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if media for user has reached the end of the list.
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
fun doesMediaListForUserHaveMorePages(userName: String): Boolean {
|
||||
val key = "user_$userName"
|
||||
return if (continuationExists.containsKey(key)) {
|
||||
continuationExists[key]!!
|
||||
} else true
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes a keyword as input and returns a list of Media objects filtered using image generator query
|
||||
* It uses the generator query API to get the images searched using a query, 10 at a time.
|
||||
*
|
||||
* @param keyword the search keyword
|
||||
* @param limit
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
fun getMediaListFromSearch(
|
||||
keyword: String?,
|
||||
limit: Int,
|
||||
offset: Int
|
||||
): Single<MwQueryResponse> {
|
||||
return mediaInterface.getMediaListFromSearch(keyword, limit, offset)
|
||||
}
|
||||
|
||||
private fun responseToMediaList(
|
||||
response: Observable<MwQueryResponse>,
|
||||
key: String
|
||||
): Single<List<Media>> {
|
||||
return response.flatMap { mwQueryResponse: MwQueryResponse? ->
|
||||
if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!!
|
||||
.pages()
|
||||
) {
|
||||
return@flatMap Observable.empty<MwQueryPage>()
|
||||
}
|
||||
if (mwQueryResponse.continuation() != null) {
|
||||
continuationStore[key] = mwQueryResponse.continuation()
|
||||
continuationExists[key] = true
|
||||
} else {
|
||||
continuationExists[key] = false
|
||||
}
|
||||
Observable.fromIterable(mwQueryResponse.query()!!.pages())
|
||||
}
|
||||
.map { page: MwQueryPage? -> Media.from(page) }
|
||||
.collect(
|
||||
{ ArrayList() }
|
||||
) { obj: MutableList<Media>, e: Media ->
|
||||
obj.add(
|
||||
e
|
||||
)
|
||||
}.map { it.toList() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Media object from the imageInfo API
|
||||
*
|
||||
* @param titles the tiles to be searched for. Can be filename or template name
|
||||
* @return
|
||||
*/
|
||||
fun getMedia(titles: String?): Single<Media> {
|
||||
return mediaInterface.getMedia(titles)
|
||||
.flatMap { mwQueryResponse: MwQueryResponse? ->
|
||||
if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!!
|
||||
.firstPage()
|
||||
) {
|
||||
return@flatMap Observable.empty<MwQueryPage>()
|
||||
}
|
||||
Observable.just(mwQueryResponse.query()!!.firstPage())
|
||||
}
|
||||
.map { page: MwQueryPage? -> Media.from(page) }
|
||||
.single(Media.EMPTY)
|
||||
}
|
||||
|
||||
/**
|
||||
* The method returns the picture of the day
|
||||
*
|
||||
* @return Media object corresponding to the picture of the day
|
||||
*/
|
||||
val pictureOfTheDay: Single<Media>
|
||||
get() {
|
||||
val date =
|
||||
CommonsDateUtil.getIso8601DateFormatShort().format(Date())
|
||||
Timber.d("Current date is %s", date)
|
||||
val template = "Template:Potd/$date"
|
||||
return mediaInterface.getMediaWithGenerator(template)
|
||||
.flatMap { mwQueryResponse: MwQueryResponse? ->
|
||||
if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!!
|
||||
.firstPage()
|
||||
) {
|
||||
return@flatMap Observable.empty<MwQueryPage>()
|
||||
}
|
||||
Observable.just(mwQueryResponse.query()!!.firstPage())
|
||||
}
|
||||
.map { page: MwQueryPage? -> Media.from(page) }
|
||||
.single(Media.EMPTY)
|
||||
}
|
||||
|
||||
fun getPageHtml(title: String?): Single<String> {
|
||||
return mediaInterface.getPageHtml(title)
|
||||
.filter { obj: MwParseResponse -> obj.success() }
|
||||
.map { obj: MwParseResponse -> obj.parse() }
|
||||
.map { obj: MwParseResult? -> obj!!.text() }
|
||||
.first("")
|
||||
}
|
||||
|
||||
/**
|
||||
* @return caption for image using wikibaseIdentifier
|
||||
*/
|
||||
fun getCaptionByWikibaseIdentifier(wikibaseIdentifier: String?): Single<String> {
|
||||
return mediaDetailInterface.getEntityForImage(
|
||||
Locale.getDefault().language,
|
||||
wikibaseIdentifier
|
||||
)
|
||||
.map { mediaDetailResponse: Entities ->
|
||||
if (isSuccess(mediaDetailResponse)) {
|
||||
for (wikibaseItem in mediaDetailResponse.entities().values) {
|
||||
for (label in wikibaseItem.labels().values) {
|
||||
return@map label.value()
|
||||
}
|
||||
}
|
||||
}
|
||||
NO_CAPTION
|
||||
}
|
||||
.singleOrError()
|
||||
}
|
||||
|
||||
fun doesPageContainMedia(title: String?): Single<Boolean> {
|
||||
return pageMediaInterface.getMediaList(title)
|
||||
.map { it.items.isNotEmpty() }
|
||||
}
|
||||
|
||||
private fun isSuccess(response: Entities?): Boolean {
|
||||
return response != null && response.success == 1 && response.entities() != null
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Structured data from API
|
||||
*
|
||||
* @param filename
|
||||
* @return a map containing caption and depictions (empty string in the map if no caption/depictions)
|
||||
*/
|
||||
fun getDepictions(filename: String?): Single<Depictions> {
|
||||
return mediaDetailInterface.fetchEntitiesByFileName(
|
||||
Locale.getDefault().language, filename
|
||||
)
|
||||
.map { entities: Entities? ->
|
||||
from(
|
||||
entities!!,
|
||||
this
|
||||
)
|
||||
}
|
||||
.singleOrError()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets labels for Depictions using Entity Id from MediaWikiAPI
|
||||
*
|
||||
* @param entityId EntityId (Ex: Q81566) of the depict entity
|
||||
* @return label
|
||||
*/
|
||||
fun getLabelForDepiction(
|
||||
entityId: String?,
|
||||
language: String
|
||||
): Single<String> {
|
||||
return mediaDetailInterface.getEntity(entityId)
|
||||
.map { entities: Entities ->
|
||||
if (isSuccess(entities)) {
|
||||
for (entity in entities.entities().values) {
|
||||
val languageToLabelMap =
|
||||
entity.labels()
|
||||
if (languageToLabelMap.containsKey(language)) {
|
||||
return@map languageToLabelMap[language]!!.value()
|
||||
}
|
||||
for (label in languageToLabelMap.values) {
|
||||
return@map label.value()
|
||||
}
|
||||
}
|
||||
}
|
||||
throw RuntimeException("failed getEntities")
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntities(entityId: String?): Single<Entities> {
|
||||
return mediaDetailInterface.getEntity(entityId)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NO_CAPTION = "No caption"
|
||||
private const val NO_DEPICTION = "No depiction"
|
||||
}
|
||||
|
||||
init {
|
||||
continuationStore =
|
||||
HashMap()
|
||||
continuationExists = HashMap()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package fr.free.nrw.commons.media
|
||||
|
||||
import fr.free.nrw.commons.media.model.PageMediaListResponse
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
|
|
@ -15,5 +15,5 @@ interface PageMediaInterface {
|
|||
* @param title the title of the page
|
||||
*/
|
||||
@GET("api/rest_v1/page/media-list/{title}")
|
||||
fun getMediaList(@Path("title") title: String?): Observable<PageMediaListResponse?>?
|
||||
}
|
||||
fun getMediaList(@Path("title") title: String?): Single<PageMediaListResponse>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,21 @@
|
|||
package fr.free.nrw.commons.contributions
|
||||
|
||||
import android.content.Context
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.auth.SessionManager
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import fr.free.nrw.commons.utils.NetworkUtilsTest
|
||||
import fr.free.nrw.commons.utils.createMockDataSourceFactory
|
||||
import io.reactivex.Scheduler
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import io.reactivex.schedulers.TestScheduler
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers.*
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.ArgumentMatchers.anyList
|
||||
import org.mockito.ArgumentMatchers.anyString
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.lang.RuntimeException
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* The unit test class for ContributionBoundaryCallbackTest
|
||||
|
|
@ -136,4 +130,4 @@ class ContributionBoundaryCallbackTest {
|
|||
verifyZeroInteractions(repository);
|
||||
verify(mediaClient).getMediaListForUser(anyString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,20 +6,18 @@ import fr.free.nrw.commons.media.model.PageMediaListItem
|
|||
import fr.free.nrw.commons.media.model.PageMediaListResponse
|
||||
import fr.free.nrw.commons.utils.CommonsDateUtil
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import junit.framework.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.*
|
||||
import org.mockito.Mockito.*
|
||||
import org.wikipedia.dataclient.mwapi.ImageDetails
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryPage
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryResponse
|
||||
import org.wikipedia.dataclient.mwapi.MwQueryResult
|
||||
import org.wikipedia.gallery.ImageInfo
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.ArgumentMatchers.*
|
||||
import java.util.*
|
||||
import org.mockito.Captor
|
||||
import org.mockito.Mockito.*
|
||||
|
||||
|
||||
class MediaClientTest {
|
||||
|
|
@ -30,6 +28,9 @@ class MediaClientTest {
|
|||
@Mock
|
||||
internal var pageMediaInterface: PageMediaInterface? = null
|
||||
|
||||
@Mock
|
||||
internal var mediaDetailInterface: MediaDetailInterface? = null
|
||||
|
||||
@InjectMocks
|
||||
var mediaClient: MediaClient? = null
|
||||
|
||||
|
|
@ -168,7 +169,7 @@ class MediaClientTest {
|
|||
`when`(mediaInterface!!.getMediaWithGenerator(filenameCaptor!!.capture()))
|
||||
.thenReturn(Observable.just(mockResponse))
|
||||
|
||||
assertEquals("Test", mediaClient!!.getPictureOfTheDay().blockingGet().filename)
|
||||
assertEquals("Test", mediaClient!!.pictureOfTheDay.blockingGet().filename)
|
||||
assertEquals(template, filenameCaptor.value);
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +261,7 @@ class MediaClientTest {
|
|||
val mock = mock(PageMediaListResponse::class.java)
|
||||
whenever(mock.items).thenReturn(listOf<PageMediaListItem>(mock(PageMediaListItem::class.java)))
|
||||
`when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString()))
|
||||
.thenReturn(Observable.just(mock))
|
||||
.thenReturn(Single.just(mock))
|
||||
|
||||
mediaClient!!.doesPageContainMedia("Test").test().assertValue(true)
|
||||
}
|
||||
|
|
@ -270,7 +271,7 @@ class MediaClientTest {
|
|||
val mock = mock(PageMediaListResponse::class.java)
|
||||
whenever(mock.items).thenReturn(listOf<PageMediaListItem>())
|
||||
`when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString()))
|
||||
.thenReturn(Observable.just(mock))
|
||||
.thenReturn(Single.just(mock))
|
||||
|
||||
mediaClient!!.doesPageContainMedia("Test").test().assertValue(false)
|
||||
}
|
||||
|
|
@ -285,4 +286,4 @@ class MediaClientTest {
|
|||
|
||||
assertEquals("", mediaClient!!.getPageHtml("abcde").blockingGet())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue