diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt index 13b7d1cd3..022563cd7 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt @@ -1,12 +1,17 @@ package fr.free.nrw.commons.explore.depictions +import android.annotation.SuppressLint import fr.free.nrw.commons.mwapi.Binding import fr.free.nrw.commons.mwapi.SparqlResponse import fr.free.nrw.commons.upload.depicts.DepictsInterface import fr.free.nrw.commons.upload.structure.depictions.DepictedItem +import fr.free.nrw.commons.upload.structure.depictions.get +import fr.free.nrw.commons.wikidata.WikidataProperties import fr.free.nrw.commons.wikidata.model.DepictSearchItem import io.reactivex.Single +import org.wikipedia.wikidata.DataValue import org.wikipedia.wikidata.Entities +import org.wikipedia.wikidata.Statement_partial import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -38,7 +43,50 @@ class DepictsClient @Inject constructor(private val depictsInterface: DepictsInt }.mapToDepictions() } + /** + * Fetches Entities from ids ex. "Q1233|Q546" and converts them into DepictedItem + */ + @SuppressLint("CheckResult") private fun Single.mapToDepictions() = flatMap(::getEntities) - .map { it.entities().values.map(::DepictedItem) } + .map { entities -> + entities.entities().values.map { entity -> + if (entity.descriptions().byLanguageOrFirstOrEmpty() == "") { + val entities: Entities = getEntities(entity[WikidataProperties.INSTANCE_OF] + .toIds()[0]).blockingGet() + val nameAsDescription = entities.entities().values.first().labels() + .byLanguageOrFirstOrEmpty() + DepictedItem( + entity, + entity.labels().byLanguageOrFirstOrEmpty(), + nameAsDescription + ) + } else { + DepictedItem( + entity, + entity.labels().byLanguageOrFirstOrEmpty(), + entity.descriptions().byLanguageOrFirstOrEmpty() + ) + } + } + } + + /** + * Tries to get Entities.Label by default language from the map. + * If that returns null, Tries to retrieve first element from the map. + * If that still returns null, function returns "". + */ + private fun Map.byLanguageOrFirstOrEmpty() = + let { + it[Locale.getDefault().language] ?: it.values.firstOrNull() }?.value() ?: "" + + /** + * returns list of id ex. "Q2323" from Statement_partial + */ + private fun List?.toIds(): List { + return this?.map { it.mainSnak.dataValue } + ?.filterIsInstance() + ?.map { it.value.id } + ?: emptyList() + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt index c1b4aa079..e0bb4e24f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt @@ -46,7 +46,7 @@ data class DepictedItem constructor( place.longDescription ) - private constructor(entity: Entities.Entity, name: String, description: String) : this( + constructor(entity: Entities.Entity, name: String, description: String) : this( name, description, entity[IMAGE].primaryImageValue?.let { diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/DepictsClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/DepictsClientTest.kt index b0f4fcf2e..505d7e85d 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/DepictsClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/DepictsClientTest.kt @@ -7,14 +7,14 @@ import fr.free.nrw.commons.mwapi.Binding import fr.free.nrw.commons.mwapi.Result import fr.free.nrw.commons.mwapi.SparqlResponse import fr.free.nrw.commons.upload.depicts.DepictsInterface +import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import fr.free.nrw.commons.wikidata.model.DepictSearchResponse import io.reactivex.Single import org.junit.Before -import org.junit.Ignore import org.junit.Test import org.mockito.Mock import org.mockito.MockitoAnnotations -import org.wikipedia.wikidata.Entities +import org.wikipedia.wikidata.* class DepictsClientTest { @@ -29,7 +29,6 @@ class DepictsClientTest { } @Test - @Ignore() fun searchForDepictions() { val depictSearchResponse = mock() whenever(depictsInterface.searchForDepicts("query", "1", "en", "en", "0")) @@ -52,7 +51,7 @@ class DepictsClientTest { } @Test - fun toDepictions() { + fun `Test toDepictions when description is empty`() { val sparqlResponse = mock() val result = mock() whenever(sparqlResponse.results).thenReturn(result) @@ -62,10 +61,51 @@ class DepictsClientTest { whenever(binding1.id).thenReturn("1") whenever(binding2.id).thenReturn("2") val entities = mock() + val entity = mock() + val statementPartial = mock() whenever(depictsInterface.getEntities("1|2")).thenReturn(Single.just(entities)) - whenever(entities.entities()).thenReturn(emptyMap()) + whenever(entities.entities()).thenReturn(mapOf("en" to entity)) + whenever(entity.statements).thenReturn(mapOf("P31" to listOf(statementPartial))) + whenever(statementPartial.mainSnak).thenReturn( + Snak_partial("test", "P31", + DataValue.EntityId( + WikiBaseEntityValue("wikibase-entityid", "Q10", 10L) + ) + ) + ) + whenever(depictsInterface.getEntities("Q10")).thenReturn(Single.just(entities)) + whenever(entity.id()).thenReturn("Q10") depictsClient.toDepictions(Single.just(sparqlResponse)) .test() - .assertValue(emptyList()) + .assertValue(listOf( + DepictedItem("", "", null, + listOf("Q10"), emptyList(), false, "Q10") + )) + } + + @Test + fun `Test toDepictions when description is not empty`() { + val sparqlResponse = mock() + val result = mock() + whenever(sparqlResponse.results).thenReturn(result) + val binding1 = mock() + val binding2 = mock() + whenever(result.bindings).thenReturn(listOf(binding1, binding2)) + whenever(binding1.id).thenReturn("1") + whenever(binding2.id).thenReturn("2") + val entities = mock() + val entity = mock() + whenever(depictsInterface.getEntities("1|2")).thenReturn(Single.just(entities)) + whenever(entities.entities()).thenReturn(mapOf("en" to entity)) + whenever(entity.descriptions()).thenReturn(mapOf("en" to + Entities.Label("en", "Test description") + )) + whenever(entity.id()).thenReturn("Q10") + depictsClient.toDepictions(Single.just(sparqlResponse)) + .test() + .assertValue(listOf( + DepictedItem("", "", null, listOf("Q10"), + emptyList(), false, "Q10") + )) } } diff --git a/data-client/src/main/java/org/wikipedia/wikidata/Entities.java b/data-client/src/main/java/org/wikipedia/wikidata/Entities.java index a320111fa..86b2002f4 100644 --- a/data-client/src/main/java/org/wikipedia/wikidata/Entities.java +++ b/data-client/src/main/java/org/wikipedia/wikidata/Entities.java @@ -78,6 +78,11 @@ public class Entities extends MwResponse implements PostProcessingTypeAdapter.Po @Nullable private String language; @Nullable private String value; + public Label(@Nullable final String language, @Nullable final String value) { + this.language = language; + this.value = value; + } + @NonNull public String language() { return StringUtils.defaultString(language); }