diff --git a/app/build.gradle b/app/build.gradle index d4758f332..638a4048a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,7 +76,7 @@ dependencies { testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5" // Unit testing - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13' testImplementation 'org.robolectric:robolectric:4.3' testImplementation 'androidx.test:core:1.2.0' testImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1' diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index e1bb1968e..c08dfbe04 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -31,6 +31,7 @@ import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.utils.DialogUtil; +import fr.free.nrw.commons.wikidata.WikidataEditService; import java.util.Locale; import javax.inject.Inject; import javax.inject.Named; @@ -41,7 +42,8 @@ import org.wikipedia.dataclient.WikiSite; */ public class ContributionsListFragment extends CommonsDaggerSupportFragment implements - ContributionsListContract.View, ContributionsListAdapter.Callback, WikipediaInstructionsDialogFragment.Callback { + ContributionsListContract.View, ContributionsListAdapter.Callback, + WikipediaInstructionsDialogFragment.Callback { private static final String RV_STATE = "rv_scroll_state"; @@ -275,7 +277,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl } - public Media getMediaAtPosition(final int i) { return adapter.getContributionForPosition(i); } @@ -291,13 +292,14 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl */ @Override public void onConfirmClicked(@Nullable Contribution contribution, boolean copyWikicode) { - if(copyWikicode) { + if (copyWikicode) { String wikicode = contribution.getWikiCode(); Utils.copy("wikicode", wikicode, getContext()); } - final String url = languageWikipediaSite.mobileUrl() + "/wiki/" + contribution.getWikidataPlace() - .getWikipediaPageTitle(); + final String url = + languageWikipediaSite.mobileUrl() + "/wiki/" + contribution.getWikidataPlace() + .getWikipediaPageTitle(); Utils.handleWebUrl(getContext(), Uri.parse(url)); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 5271468f2..59b7083b1 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -21,24 +21,16 @@ import fr.free.nrw.commons.contributions.MainActivity; import fr.free.nrw.commons.di.CommonsApplicationModule; import fr.free.nrw.commons.di.CommonsDaggerService; import fr.free.nrw.commons.media.MediaClient; -import fr.free.nrw.commons.utils.CommonsDateUtil; import fr.free.nrw.commons.wikidata.WikidataEditService; -import io.reactivex.Completable; import io.reactivex.Observable; import io.reactivex.Scheduler; -import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Action; -import io.reactivex.functions.Consumer; import io.reactivex.processors.PublishProcessor; import io.reactivex.schedulers.Schedulers; import java.io.File; import java.io.IOException; -import java.text.ParseException; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; @@ -313,7 +305,7 @@ public class UploadService extends CommonsDaggerService { .add(wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution)); WikidataPlace wikidataPlace = contribution.getWikidataPlace(); if (wikidataPlace != null && wikidataPlace.getImageValue() == null) { - wikidataEditService.createImageClaim(wikidataPlace, uploadResult); + wikidataEditService.createClaim(wikidataPlace, uploadResult.getFilename(), contribution.getCaptions()); } saveCompletedContribution(contribution, uploadResult); } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java index 24f518b52..ebee708e9 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java @@ -1,6 +1,6 @@ package fr.free.nrw.commons.wikidata; -import fr.free.nrw.commons.upload.WikidataItem; +import com.google.gson.Gson; import org.jetbrains.annotations.NotNull; import javax.inject.Inject; @@ -9,64 +9,38 @@ import javax.inject.Singleton; import fr.free.nrw.commons.wikidata.model.AddEditTagResponse; import io.reactivex.Observable; import io.reactivex.ObservableSource; -import okhttp3.MediaType; -import okhttp3.RequestBody; +import org.wikipedia.wikidata.Statement_partial; @Singleton public class WikidataClient { - private final WikidataInterface wikidataInterface; + private final WikidataInterface wikidataInterface; + private final Gson gson; - @Inject - public WikidataClient(WikidataInterface wikidataInterface) { - this.wikidataInterface = wikidataInterface; - } + @Inject + public WikidataClient(WikidataInterface wikidataInterface, final Gson gson) { + this.wikidataInterface = wikidataInterface; + this.gson = gson; + } - /** - * Create wikidata claim to add P18 value - * @param entity wikidata entity ID - * @param value value of the P18 edit - * @return revisionID of the edit - */ - Observable createImageClaim(WikidataItem entity, String value) { - return getCsrfToken() - .flatMap(csrfToken -> wikidataInterface.postCreateClaim( - toRequestBody(entity.getId()), - toRequestBody("value"), - toRequestBody(WikidataProperties.IMAGE.getPropertyName()), - toRequestBody(value), - toRequestBody("en"), - toRequestBody(csrfToken))) - .map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid()); - } + /** + * Create wikidata claim to add P18 value + * + * @return revisionID of the edit + */ + Observable setClaim(Statement_partial claim, String tags) { + return getCsrfToken() + .flatMap(csrfToken -> wikidataInterface.postSetClaim(gson.toJson(claim), tags, csrfToken)) + .map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid()); + } - /** - * Converts string value to RequestBody for multipart request - */ - private RequestBody toRequestBody(String value) { - return RequestBody.create(MediaType.parse("text/plain"), value); - } - - /** - * Get csrf token for wikidata edit - */ - @NotNull - private Observable getCsrfToken() { - return wikidataInterface.getCsrfToken().map(mwQueryResponse -> mwQueryResponse.query().csrfToken()); - } - - /** - * Add edit tag for a given revision ID. The app currently uses this to tag P18 edits - * @param revisionId revision ID of the page edited - * @param tag to be added - * @param reason to be mentioned - */ - ObservableSource addEditTag(Long revisionId, String tag, String reason) { - return getCsrfToken() - .flatMap(csrfToken -> wikidataInterface.addEditTag(String.valueOf(revisionId), - tag, - reason, - csrfToken)); - } + /** + * Get csrf token for wikidata edit + */ + @NotNull + private Observable getCsrfToken() { + return wikidataInterface.getCsrfToken() + .map(mwQueryResponse -> mwQueryResponse.query().csrfToken()); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java index e761c68ed..ccd791a41 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java @@ -20,49 +20,58 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.UUID; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.wikipedia.dataclient.mwapi.MwPostResponse; +import org.wikipedia.wikidata.DataValue; +import org.wikipedia.wikidata.DataValue.ValueString; import org.wikipedia.wikidata.EditClaim; +import org.wikipedia.wikidata.Snak_partial; +import org.wikipedia.wikidata.Statement_partial; +import org.wikipedia.wikidata.WikiBaseMonolingualTextValue; import timber.log.Timber; /** - * This class is meant to handle the Wikidata edits made through the app - * It will talk with MediaWiki Apis to make the necessary calls, log the edits and fire listeners - * on successful edits + * This class is meant to handle the Wikidata edits made through the app It will talk with MediaWiki + * Apis to make the necessary calls, log the edits and fire listeners on successful edits */ @Singleton public class WikidataEditService { - private static final String COMMONS_APP_TAG = "wikimedia-commons-app"; - private static final String COMMONS_APP_EDIT_REASON = "Add tag for edits made using Android Commons app"; + public static final String COMMONS_APP_TAG = "wikimedia-commons-app"; - private final Context context; - private final WikidataEditListener wikidataEditListener; - private final JsonKvStore directKvStore; - private final WikiBaseClient wikiBaseClient; - private final WikidataClient wikidataClient; - private final Gson gson; + private final Context context; + private final WikidataEditListener wikidataEditListener; + private final JsonKvStore directKvStore; + private final WikiBaseClient wikiBaseClient; + private final WikidataClient wikidataClient; + private final Gson gson; @Inject - public WikidataEditService(final Context context, + public WikidataEditService(final Context context, final WikidataEditListener wikidataEditListener, @Named("default_preferences") final JsonKvStore directKvStore, final WikiBaseClient wikiBaseClient, final WikidataClient wikidataClient, final Gson gson) { - this.context = context; - this.wikidataEditListener = wikidataEditListener; - this.directKvStore = directKvStore; - this.wikiBaseClient = wikiBaseClient; - this.wikidataClient = wikidataClient; + this.context = context; + this.wikidataEditListener = wikidataEditListener; + this.directKvStore = directKvStore; + this.wikiBaseClient = wikiBaseClient; + this.wikidataClient = wikidataClient; this.gson = gson; } /** - * Edits the wikibase entity by adding DEPICTS property. - * Adding DEPICTS property requires call to the wikibase API to set tag against the entity. + * Edits the wikibase entity by adding DEPICTS property. Adding DEPICTS property requires call to + * the wikibase API to set tag against the entity. */ @SuppressLint("CheckResult") private Observable addDepictsProperty(final String fileEntityId, @@ -70,7 +79,7 @@ public class WikidataEditService { final EditClaim data = editClaim( ConfigUtils.isBetaFlavour() ? "Q10" // Wikipedia:Sandbox (Q10) - : depictedItem.getId() + : depictedItem.getId() ); return wikiBaseClient.postEditEntity(PAGE_ID_PREFIX + fileEntityId, gson.toJson(data)) @@ -81,44 +90,46 @@ public class WikidataEditService { Timber.d("Unable to set DEPICTS property for %s", fileEntityId); } }) - .doOnError( throwable -> { + .doOnError(throwable -> { Timber.e(throwable, "Error occurred while setting DEPICTS property"); ViewUtil.showLongToast(context, throwable.toString()); }) .subscribeOn(Schedulers.io()); - } + } private EditClaim editClaim(final String entityId) { return EditClaim.from(entityId, WikidataProperties.DEPICTS.getPropertyName()); } /** - * Show a success toast when the edit is made successfully - */ - private void showSuccessToast(final String wikiItemName) { - final String successStringTemplate = context.getString(R.string.successful_wikidata_edit); - final String successMessage = String.format(Locale.getDefault(), successStringTemplate, wikiItemName); - ViewUtil.showLongToast(context, successMessage); - } + * Show a success toast when the edit is made successfully + */ + private void showSuccessToast(final String wikiItemName) { + final String successStringTemplate = context.getString(R.string.successful_wikidata_edit); + final String successMessage = String + .format(Locale.getDefault(), successStringTemplate, wikiItemName); + ViewUtil.showLongToast(context, successMessage); + } /** - * Adds label to Wikidata using the fileEntityId and the edit token, obtained from csrfTokenClient - * - * @param fileEntityId - * @return - */ + * Adds label to Wikidata using the fileEntityId and the edit token, obtained from + * csrfTokenClient + * + * @param fileEntityId + * @return + */ - @SuppressLint("CheckResult") - private Observable addCaption(final long fileEntityId, final String languageCode, - final String captionValue) { - return wikiBaseClient.addLabelstoWikidata(fileEntityId, languageCode, captionValue) - .doOnNext(mwPostResponse -> onAddCaptionResponse(fileEntityId, mwPostResponse) ) - .doOnError(throwable -> { - Timber.e(throwable, "Error occurred while setting Captions"); - ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure)); - }) - .map(mwPostResponse -> mwPostResponse != null); - } + @SuppressLint("CheckResult") + private Observable addCaption(final long fileEntityId, final String languageCode, + final String captionValue) { + return wikiBaseClient.addLabelstoWikidata(fileEntityId, languageCode, captionValue) + .doOnNext(mwPostResponse -> onAddCaptionResponse(fileEntityId, mwPostResponse)) + .doOnError(throwable -> { + Timber.e(throwable, "Error occurred while setting Captions"); + ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure)); + }) + .map(mwPostResponse -> mwPostResponse != null); + } private void onAddCaptionResponse(Long fileEntityId, MwPostResponse response) { if (response != null) { @@ -128,29 +139,41 @@ public class WikidataEditService { } } - public void createImageClaim(@Nullable final WikidataPlace wikidataPlace, final UploadResult imageUpload) { + public void createClaim(@Nullable final WikidataPlace wikidataPlace, final String fileName, final + Map captions) { if (!(directKvStore.getBoolean("Picture_Has_Correct_Location", true))) { - Timber.d("Image location and nearby place location mismatched, so Wikidata item won't be edited"); + Timber + .d("Image location and nearby place location mismatched, so Wikidata item won't be edited"); return; } - editWikidataImageProperty(wikidataPlace, imageUpload); + addImageAndMediaLegends(wikidataPlace, fileName, captions); } - @SuppressLint("CheckResult") - private void editWikidataImageProperty(final WikidataItem wikidataItem, final UploadResult imageUpload) { - wikidataClient.createImageClaim(wikidataItem, String.format("\"%s\"", imageUpload.getFilename())) - .flatMap(revisionId -> { - if (revisionId != -1) { - return wikidataClient.addEditTag(revisionId, COMMONS_APP_TAG, COMMONS_APP_EDIT_REASON); - } - throw new RuntimeException("Unable to edit wikidata item"); - }) - .subscribeOn(Schedulers.io()) + public void addImageAndMediaLegends(final WikidataItem wikidataItem, final String fileName, + final Map captions) { + final Snak_partial p18 = new Snak_partial("value", WikidataProperties.IMAGE.getPropertyName(), + new ValueString(fileName.replace("File:", ""))); + + final List snaks = new ArrayList<>(); + for (final Map.Entry entry : captions.entrySet()) { + snaks.add(new Snak_partial("value", + WikidataProperties.MEDIA_LEGENDS.getPropertyName(), new DataValue.MonoLingualText( + new WikiBaseMonolingualTextValue(entry.getValue(), entry.getKey())))); + } + + final String id = wikidataItem.getId() + "$" + UUID.randomUUID().toString(); + final Statement_partial claim = new Statement_partial(p18, "statement", "normal", id, + Collections.singletonMap(WikidataProperties.MEDIA_LEGENDS.getPropertyName(), snaks), + Arrays.asList(WikidataProperties.MEDIA_LEGENDS.getPropertyName())); + + wikidataClient.setClaim(claim, COMMONS_APP_TAG).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(revisionId -> handleImageClaimResult(wikidataItem, String.valueOf(revisionId)), throwable -> { - Timber.e(throwable, "Error occurred while making claim"); - ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure)); - }); + .subscribe(revisionId -> handleImageClaimResult(wikidataItem, String.valueOf(revisionId)), + throwable -> { + Timber.e(throwable, "Error occurred while making claim"); + ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure)); + }); + ; } private void handleImageClaimResult(final WikidataItem wikidataItem, final String revisionId) { @@ -185,9 +208,9 @@ public class WikidataEditService { } } ).subscribe( - success -> Timber.d("edit response: %s", success), - throwable -> Timber.e(throwable, "posting edits failed") - ); + success -> Timber.d("edit response: %s", success), + throwable -> Timber.e(throwable, "posting edits failed") + ); } private Observable captionEdits(Contribution contribution, Long fileEntityId) { @@ -202,6 +225,6 @@ public class WikidataEditService { depictedItems.add(wikidataPlace); } return Observable.fromIterable(depictedItems) - .concatMap( wikidataItem -> addDepictsProperty(fileEntityId.toString(), wikidataItem)); + .concatMap(wikidataItem -> addDepictsProperty(fileEntityId.toString(), wikidataItem)); } } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java index 25d5f43ea..9f240c150 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.wikidata; import androidx.annotation.NonNull; +import com.google.gson.JsonObject; import org.wikipedia.dataclient.mwapi.MwQueryResponse; import fr.free.nrw.commons.wikidata.model.AddEditTagResponse; @@ -20,35 +21,21 @@ import static org.wikipedia.dataclient.Service.MW_API_PREFIX; public interface WikidataInterface { - /** - * Wikidata create claim API. Posts a new claim for the given entity ID - */ - @Headers("Cache-Control: no-cache") - @POST("w/api.php?format=json&errorformat=plaintext&action=wbcreateclaim&errorlang=uselang") - @Multipart - Observable postCreateClaim(@NonNull @Part("entity") RequestBody entity, - @NonNull @Part("snaktype") RequestBody snakType, - @NonNull @Part("property") RequestBody property, - @NonNull @Part("value") RequestBody value, - @NonNull @Part("uselang") RequestBody useLang, - @NonNull @Part("token") RequestBody token); + /** + * Get edit token for wikidata wiki site + */ + @Headers("Cache-Control: no-cache") + @GET(MW_API_PREFIX + "action=query&meta=tokens&type=csrf") + @NonNull + Observable getCsrfToken(); - /** - * Add edit tag and reason for any revision - */ - @Headers("Cache-Control: no-cache") - @POST(MW_API_PREFIX + "action=tag") - @FormUrlEncoded - Observable addEditTag(@NonNull @Field("revid") String revId, - @NonNull @Field("add") String tagName, - @NonNull @Field("reason") String reason, - @NonNull @Field("token") String token); - - /** - * Get edit token for wikidata wiki site - */ - @Headers("Cache-Control: no-cache") - @GET(MW_API_PREFIX + "action=query&meta=tokens&type=csrf") - @NonNull - Observable getCsrfToken(); + /** + * Wikidata create claim API. Posts a new claim for the given entity ID + */ + @Headers("Cache-Control: no-cache") + @POST("w/api.php?format=json&action=wbsetclaim") + @FormUrlEncoded + Observable postSetClaim(@NonNull @Field("claim") String request, + @NonNull @Field("tags") String tags, + @NonNull @Field("token") String token); } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt index 14db02a27..dbeb0dc76 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt @@ -6,5 +6,6 @@ enum class WikidataProperties(val propertyName: String) { IMAGE("P18"), DEPICTS(BuildConfig.DEPICTS_PROPERTY), COMMONS_CATEGORY("P373"), - INSTANCE_OF("P31"); + INSTANCE_OF("P31"), + MEDIA_LEGENDS("P2096"); } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataClientTest.kt index ad51203de..a1ef96274 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataClientTest.kt @@ -1,7 +1,9 @@ package fr.free.nrw.commons.wikidata -import com.nhaarman.mockitokotlin2.mock -import fr.free.nrw.commons.wikidata.model.AddEditTagResponse +import com.google.gson.Gson +import com.nhaarman.mockitokotlin2.whenever +import fr.free.nrw.commons.wikidata.model.PageInfo +import fr.free.nrw.commons.wikidata.model.WbCreateClaimResponse import io.reactivex.Observable import org.junit.Before import org.junit.Test @@ -14,12 +16,16 @@ import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations import org.wikipedia.dataclient.mwapi.MwQueryResponse import org.wikipedia.dataclient.mwapi.MwQueryResult +import org.wikipedia.wikidata.Statement_partial class WikidataClientTest { @Mock internal var wikidataInterface: WikidataInterface? = null + @Mock + internal var gson: Gson? = null + @InjectMocks var wikidataClient: WikidataClient? = null @@ -35,26 +41,18 @@ class WikidataClientTest { .thenReturn(Observable.just(mwQueryResponse)) } - @Test - fun createClaim() { - `when`( - wikidataInterface!!.postCreateClaim( - any(), - any(), - any(), - any(), - any(), - any() - ) - ) - .thenReturn(Observable.just(mock())) - wikidataClient!!.createImageClaim(mock(), "test.jpg") - } - @Test fun addEditTag() { - `when`(wikidataInterface!!.addEditTag(anyString(), anyString(), anyString(), anyString())) - .thenReturn(Observable.just(mock(AddEditTagResponse::class.java))) - wikidataClient!!.addEditTag(1L, "test", "test") + val response = mock(WbCreateClaimResponse::class.java) + val pageInfo = mock(PageInfo::class.java) + whenever(pageInfo.lastrevid).thenReturn(1) + whenever(response.pageinfo).thenReturn(pageInfo) + `when`(wikidataInterface!!.postSetClaim(anyString(), anyString(), anyString())) + .thenReturn(Observable.just(response)) + whenever(gson!!.toJson(any(Statement_partial::class.java))).thenReturn("claim") + val request = mock(Statement_partial::class.java) + + val claim = wikidataClient!!.setClaim(request, "test").test() + .assertValue(1L) } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt index cc41f756c..2f6379ef3 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt @@ -1,13 +1,13 @@ package fr.free.nrw.commons.wikidata import android.content.Context +import com.google.gson.Gson import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verifyZeroInteractions import com.nhaarman.mockitokotlin2.whenever import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.upload.UploadResult import fr.free.nrw.commons.upload.WikidataPlace -import fr.free.nrw.commons.wikidata.model.AddEditTagResponse import io.reactivex.Observable import org.junit.Before import org.junit.Test @@ -15,7 +15,6 @@ import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyString import org.mockito.InjectMocks import org.mockito.Mock -import org.mockito.Mockito.* import org.mockito.MockitoAnnotations class WikidataEditServiceTest { @@ -31,6 +30,9 @@ class WikidataEditServiceTest { @Mock internal lateinit var wikibaseClient: WikiBaseClient + @Mock + internal lateinit var gson: Gson + @InjectMocks lateinit var wikidataEditService: WikidataEditService @@ -44,7 +46,7 @@ class WikidataEditServiceTest { fun noClaimsWhenLocationIsNotCorrect() { whenever(directKvStore.getBoolean("Picture_Has_Correct_Location", true)) .thenReturn(false) - wikidataEditService.createImageClaim(mock(), mock()) + wikidataEditService.createClaim(mock(), "Test.jpg", hashMapOf()) verifyZeroInteractions(wikidataClient) } @@ -52,15 +54,16 @@ class WikidataEditServiceTest { fun createImageClaim() { whenever(directKvStore.getBoolean("Picture_Has_Correct_Location", true)) .thenReturn(true) - whenever(wikidataClient.createImageClaim(any(), any())) - .thenReturn(Observable.just(1L)) - whenever(wikidataClient.addEditTag(anyLong(), anyString(), anyString())) - .thenReturn(Observable.just(mock(AddEditTagResponse::class.java))) whenever(wikibaseClient.getFileEntityId(any())).thenReturn(Observable.just(1L)) - val wikidataPlace:WikidataPlace = mock() + whenever(wikidataClient.setClaim(any(), anyString())) + .thenReturn(Observable.just(1L)) + val wikidataPlace: WikidataPlace = mock() val uploadResult = mock() whenever(uploadResult.filename).thenReturn("file") - wikidataEditService.createImageClaim(wikidataPlace, uploadResult) - verify(wikidataClient, times(1)).createImageClaim(wikidataPlace, """"file"""") + wikidataEditService.createClaim( + wikidataPlace, + uploadResult.filename, + hashMapOf() + ) } } diff --git a/data-client/src/main/java/org/wikipedia/wikidata/DataValue.kt b/data-client/src/main/java/org/wikipedia/wikidata/DataValue.kt index a1bf63577..c42ec05b9 100644 --- a/data-client/src/main/java/org/wikipedia/wikidata/DataValue.kt +++ b/data-client/src/main/java/org/wikipedia/wikidata/DataValue.kt @@ -12,7 +12,7 @@ sealed class DataValue(val type: String) { .registerSubtype(GlobeCoordinate_partial::class.java, GlobeCoordinate_partial.TYPE) .registerSubtype(Time_partial::class.java, Time_partial.TYPE) .registerSubtype(Quantity_partial::class.java, Quantity_partial.TYPE) - .registerSubtype(MonoLingualText_partial::class.java, MonoLingualText_partial.TYPE) + .registerSubtype(MonoLingualText::class.java, MonoLingualText.TYPE) } // "value": { @@ -87,7 +87,7 @@ sealed class DataValue(val type: String) { // "language": "ko" // } // } - class MonoLingualText_partial() : DataValue(TYPE) { + class MonoLingualText(val value: WikiBaseMonolingualTextValue) : DataValue(TYPE) { companion object { const val TYPE = "monolingualtext" } diff --git a/data-client/src/main/java/org/wikipedia/wikidata/Statement_partial.kt b/data-client/src/main/java/org/wikipedia/wikidata/Statement_partial.kt index 7258e354e..24d032b33 100644 --- a/data-client/src/main/java/org/wikipedia/wikidata/Statement_partial.kt +++ b/data-client/src/main/java/org/wikipedia/wikidata/Statement_partial.kt @@ -21,5 +21,8 @@ import com.google.gson.annotations.SerializedName data class Statement_partial( @SerializedName("mainsnak") val mainSnak: Snak_partial, val type: String, - val rank: String + val rank: String, + val id: String? = null, + val qualifiers: Map> = mapOf(), + @SerializedName("qualifiers-order") val qualifiersOrder: List = listOf() ) diff --git a/data-client/src/main/java/org/wikipedia/wikidata/WikiBaseMonolingualTextValue.kt b/data-client/src/main/java/org/wikipedia/wikidata/WikiBaseMonolingualTextValue.kt new file mode 100644 index 000000000..ab93fc168 --- /dev/null +++ b/data-client/src/main/java/org/wikipedia/wikidata/WikiBaseMonolingualTextValue.kt @@ -0,0 +1,13 @@ +package org.wikipedia.wikidata + +import com.google.gson.annotations.SerializedName + +/*"value": { + "type": "monolingualtext", + "value": { + "text": "some value", + "language": "en" + } +}*/ + +data class WikiBaseMonolingualTextValue(val text: String, val language: String) \ No newline at end of file