mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
* logs * Issue resolved * Logs removed * Beta working * Production GET call only for fetch images from depicted item * Code convention maintained * Code convention maintained * Test resolved * Java Docs added * Quotes added
This commit is contained in:
parent
7bcaab2442
commit
0914eeea53
6 changed files with 162 additions and 5 deletions
18
app/src/main/java/fr/free/nrw/commons/BetaConstants.kt
Normal file
18
app/src/main/java/fr/free/nrw/commons/BetaConstants.kt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package fr.free.nrw.commons
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Production variant related constants which is used in beta variant for some specific GET calls on
|
||||||
|
* production server where beta server does not work
|
||||||
|
*/
|
||||||
|
object BetaConstants {
|
||||||
|
/**
|
||||||
|
* Commons production URL which is used in beta for some specific GET calls on
|
||||||
|
* production server where beta server does not work
|
||||||
|
*/
|
||||||
|
const val COMMONS_URL = "https://commons.wikimedia.org/"
|
||||||
|
/**
|
||||||
|
* Commons production's depicts property which is used in beta for some specific GET calls on
|
||||||
|
* production server where beta server does not work
|
||||||
|
*/
|
||||||
|
const val DEPICTS_PROPERTY = "P180"
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
import fr.free.nrw.commons.BetaConstants;
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.actions.PageEditClient;
|
import fr.free.nrw.commons.actions.PageEditClient;
|
||||||
import fr.free.nrw.commons.actions.PageEditInterface;
|
import fr.free.nrw.commons.actions.PageEditInterface;
|
||||||
|
|
@ -14,6 +15,7 @@ import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
import fr.free.nrw.commons.media.MediaDetailInterface;
|
import fr.free.nrw.commons.media.MediaDetailInterface;
|
||||||
import fr.free.nrw.commons.media.MediaInterface;
|
import fr.free.nrw.commons.media.MediaInterface;
|
||||||
import fr.free.nrw.commons.media.PageMediaInterface;
|
import fr.free.nrw.commons.media.PageMediaInterface;
|
||||||
|
import fr.free.nrw.commons.media.WikidataMediaInterface;
|
||||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
||||||
import fr.free.nrw.commons.mwapi.UserInterface;
|
import fr.free.nrw.commons.mwapi.UserInterface;
|
||||||
import fr.free.nrw.commons.review.ReviewInterface;
|
import fr.free.nrw.commons.review.ReviewInterface;
|
||||||
|
|
@ -226,6 +228,20 @@ public class NetworkingModule {
|
||||||
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, MediaInterface.class);
|
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, MediaInterface.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add provider for WikidataMediaInterface
|
||||||
|
* It creates a retrofit service for the commons wiki site
|
||||||
|
* @param commonsWikiSite commonsWikiSite
|
||||||
|
* @return WikidataMediaInterface
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public WikidataMediaInterface provideWikidataMediaInterface(
|
||||||
|
@Named(NAMED_COMMONS_WIKI_SITE) final WikiSite commonsWikiSite) {
|
||||||
|
return ServiceFactory.get(commonsWikiSite,
|
||||||
|
BetaConstants.COMMONS_URL, WikidataMediaInterface.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public MediaDetailInterface providesMediaDetailInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikisite) {
|
public MediaDetailInterface providesMediaDetailInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikisite) {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
package fr.free.nrw.commons.explore.depictions.media
|
package fr.free.nrw.commons.explore.depictions.media
|
||||||
|
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
|
import fr.free.nrw.commons.explore.depictions.search.LoadFunction
|
||||||
import fr.free.nrw.commons.explore.paging.LiveDataConverter
|
import fr.free.nrw.commons.explore.paging.LiveDataConverter
|
||||||
import fr.free.nrw.commons.explore.paging.PageableBaseDataSource
|
import fr.free.nrw.commons.explore.paging.PageableBaseDataSource
|
||||||
import fr.free.nrw.commons.explore.depictions.search.LoadFunction
|
import fr.free.nrw.commons.media.WikidataMediaClient
|
||||||
import fr.free.nrw.commons.media.MediaClient
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PageableDepictedMediaDataSource @Inject constructor(
|
class PageableDepictedMediaDataSource @Inject constructor(
|
||||||
liveDataConverter: LiveDataConverter,
|
liveDataConverter: LiveDataConverter,
|
||||||
private val mediaClient: MediaClient
|
private val wikiMediaClient: WikidataMediaClient
|
||||||
) : PageableBaseDataSource<Media>(liveDataConverter) {
|
) : PageableBaseDataSource<Media>(liveDataConverter) {
|
||||||
override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int ->
|
override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int ->
|
||||||
mediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet()
|
wikiMediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package fr.free.nrw.commons.media
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.BetaConstants
|
||||||
|
import fr.free.nrw.commons.Media
|
||||||
|
import fr.free.nrw.commons.category.ContinuationClient
|
||||||
|
import fr.free.nrw.commons.explore.media.MediaConverter
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.wikipedia.dataclient.mwapi.MwQueryPage
|
||||||
|
import org.wikipedia.dataclient.mwapi.MwQueryResponse
|
||||||
|
import org.wikipedia.wikidata.Entities
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Media Client to handle custom calls to Commons MediaWiki APIs of production server
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
class WikidataMediaClient @Inject constructor(
|
||||||
|
private val wikidataMediaInterface: WikidataMediaInterface,
|
||||||
|
private val mediaDetailInterface: MediaDetailInterface,
|
||||||
|
private val mediaConverter: MediaConverter
|
||||||
|
) : ContinuationClient<MwQueryResponse, Media>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch images for depict ID
|
||||||
|
*
|
||||||
|
* @param query depictionEntityId ex. "Q9394"
|
||||||
|
* @param srlimit the number of items to fetch
|
||||||
|
* @param sroffset number of depictions already fetched,
|
||||||
|
* this is useful in implementing pagination
|
||||||
|
* @return list of images for a particular depict ID
|
||||||
|
*/
|
||||||
|
fun fetchImagesForDepictedItem(
|
||||||
|
query: String,
|
||||||
|
srlimit: Int,
|
||||||
|
sroffset: Int
|
||||||
|
): Single<List<Media>> {
|
||||||
|
return responseMapper(
|
||||||
|
wikidataMediaInterface.fetchImagesForDepictedItem(
|
||||||
|
"haswbstatement:" + BetaConstants.DEPICTS_PROPERTY + "=" + query,
|
||||||
|
srlimit.toString(),
|
||||||
|
sroffset.toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helps to map to the required data from the API response
|
||||||
|
*
|
||||||
|
* @param networkResult MwQueryResponse
|
||||||
|
* @param key for handling continuation request, this is null in this case
|
||||||
|
*/
|
||||||
|
override fun responseMapper(
|
||||||
|
networkResult: Single<MwQueryResponse>,
|
||||||
|
key: String?
|
||||||
|
): Single<List<Media>> {
|
||||||
|
return networkResult.map {
|
||||||
|
handleContinuationResponse(it.continuation(), key)
|
||||||
|
it.query()?.pages() ?: emptyList()
|
||||||
|
}.flatMap(::mediaFromPageAndEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets list of Media from MwQueryPage
|
||||||
|
*/
|
||||||
|
private fun mediaFromPageAndEntity(pages: List<MwQueryPage>): Single<List<Media>> {
|
||||||
|
return if (pages.isEmpty())
|
||||||
|
Single.just(emptyList())
|
||||||
|
else
|
||||||
|
getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" })
|
||||||
|
.map {
|
||||||
|
pages.zip(it.entities().values)
|
||||||
|
.mapNotNull { (page, entity) ->
|
||||||
|
page.imageInfo()?.let {
|
||||||
|
mediaConverter.convert(page, entity, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets Entities from IDs
|
||||||
|
*
|
||||||
|
* @param entityIds list of IDs of pages/entities ex. {"M4254154", "M11413343"}
|
||||||
|
*/
|
||||||
|
fun getEntities(entityIds: List<String>): Single<Entities> {
|
||||||
|
return if (entityIds.isEmpty())
|
||||||
|
Single.error(Exception("empty list passed for ids"))
|
||||||
|
else
|
||||||
|
mediaDetailInterface.getEntity(entityIds.joinToString("|"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package fr.free.nrw.commons.media;
|
||||||
|
|
||||||
|
import static fr.free.nrw.commons.media.MediaInterface.MEDIA_PARAMS;
|
||||||
|
|
||||||
|
import io.reactivex.Single;
|
||||||
|
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for getting Wikidata images from production server
|
||||||
|
*/
|
||||||
|
public interface WikidataMediaInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches list of images from a depiction entity
|
||||||
|
* @param query depictionEntityId ex. "haswbstatement:P180=Q9394"
|
||||||
|
* @param srlimit the number of items to fetch
|
||||||
|
* @param sroffset number of depictions already fetched,
|
||||||
|
* this is useful in implementing pagination
|
||||||
|
* @return Single<MwQueryResponse>
|
||||||
|
*/
|
||||||
|
@GET("w/api.php?action=query&format=json&formatversion=2" + //Basic parameters
|
||||||
|
"&generator=search&gsrnamespace=6" + //Search parameters
|
||||||
|
MEDIA_PARAMS)
|
||||||
|
Single<MwQueryResponse> fetchImagesForDepictedItem(@Query("gsrsearch") String query,
|
||||||
|
@Query("gsrlimit")String srlimit, @Query("gsroffset") String sroffset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.explore.depictions.media
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import fr.free.nrw.commons.media.MediaClient
|
import fr.free.nrw.commons.media.MediaClient
|
||||||
|
import fr.free.nrw.commons.media.WikidataMediaClient
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -10,7 +11,7 @@ import org.junit.Test
|
||||||
class PageableDepictedMediaDataSourceTest{
|
class PageableDepictedMediaDataSourceTest{
|
||||||
@Test
|
@Test
|
||||||
fun `loadFunction loads Media`() {
|
fun `loadFunction loads Media`() {
|
||||||
val mediaClient = mock<MediaClient>()
|
val mediaClient = mock<WikidataMediaClient>()
|
||||||
whenever(mediaClient.fetchImagesForDepictedItem("test",0,1))
|
whenever(mediaClient.fetchImagesForDepictedItem("test",0,1))
|
||||||
.thenReturn(Single.just(emptyList()))
|
.thenReturn(Single.just(emptyList()))
|
||||||
val pageableDepictedMediaDataSource = PageableDepictedMediaDataSource(mock(), mediaClient)
|
val pageableDepictedMediaDataSource = PageableDepictedMediaDataSource(mock(), mediaClient)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue