Skip to content

Commit

Permalink
Wikibase API: Return revision id after making an edit. (#796)
Browse files Browse the repository at this point in the history
* Wikibase API: Return revision id after making an edit. Closes #795

* Use Optional on getRevisionId

* Use OptionalLong
  • Loading branch information
wetneb authored Jul 1, 2023
1 parent 3d2117d commit 6205a38
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.wikidata.wdtk.wikibaseapi;

/*-
* #%L
* Wikidata Toolkit Wikibase API
* %%
* Copyright (C) 2014 - 2023 Wikidata Toolkit Developers
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import java.util.Objects;
import java.util.OptionalLong;

/**
* Holds information about a successful edit made via {@link WikibaseDataEditor}.
* The state of the entity after edit is not provided here because it is not possible
* for WDTK to determine it reliably from the response of the server. Indeed, it is
* possible that the data in the entity after the edit differs from the data in the
* entity before the edit plus the changes of the edit itself, because it can be that
* another edit touched independent parts of the entity. This can happen even if the base
* revision id is provided.
*/
public class EditingResult {

private final long revisionId;

public EditingResult(long revisionId) {
super();
this.revisionId = revisionId;
}

/**
* The identifier of the revision of the last edit made by the editing action,
* if any edit was made.
*/
public OptionalLong getLastRevisionId() {
return revisionId == 0 ? OptionalLong.empty() : OptionalLong.of(revisionId);
}

@Override
public int hashCode() {
return Objects.hash(revisionId);
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
EditingResult other = (EditingResult) obj;
return revisionId == other.revisionId;
}

@Override
public String toString() {
return "EditingResult [revisionId=" + revisionId + "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
import org.wikidata.wdtk.datamodel.interfaces.TermedStatementDocumentUpdate;
import org.wikidata.wdtk.wikibaseapi.apierrors.MediaWikiApiErrorException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;

/**
* Class that provides high-level editing functionality for Wikibase data.
*
Expand Down Expand Up @@ -530,13 +533,13 @@ public ItemDocument editItemDocument(ItemDocument itemDocument,
* @throws MediaWikiApiErrorException
* if MediaWiki API returned an error response
*/
public void editEntityDocument(
public EditingResult editEntityDocument(
EntityUpdate update, boolean clear, String summary, List<String> tags)
throws IOException, MediaWikiApiErrorException {
long revisionId = update.getBaseRevisionId();
if (!clear) {
if (update.isEmpty())
return;
return new EditingResult(0L);
if (update instanceof StatementDocumentUpdate) {
StatementDocumentUpdate typed = (StatementDocumentUpdate) update;
if (typed.getStatements().getAdded().size() == 1) {
Expand All @@ -547,9 +550,9 @@ public void editEntityDocument(
if (builder.build().equals(update)) {
String statementId = guidGenerator.freshStatementId(typed.getEntityId().getId());
Statement prepared = statement.withStatementId(statementId);
wbEditingAction.wbSetClaim(JsonSerializer.getJsonString(prepared),
JsonNode response = wbEditingAction.wbSetClaim(JsonSerializer.getJsonString(prepared),
editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
if (typed.getStatements().getReplaced().size() == 1) {
Expand All @@ -558,9 +561,9 @@ public void editEntityDocument(
Statement statement = typed.getStatements().getReplaced().values().stream().findFirst().get();
builder.updateStatements(StatementUpdateBuilder.create().replace(statement).build());
if (builder.build().equals(update)) {
wbEditingAction.wbSetClaim(JsonSerializer.getJsonString(statement),
JsonNode response = wbEditingAction.wbSetClaim(JsonSerializer.getJsonString(statement),
editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
if (!typed.getStatements().getRemoved().isEmpty()
Expand All @@ -574,8 +577,8 @@ public void editEntityDocument(
}
builder.updateStatements(statementBuilder.build());
if (builder.build().equals(update)) {
wbEditingAction.wbRemoveClaims(statementIds, editAsBot, revisionId, summary, tags);
return;
JsonNode response = wbEditingAction.wbRemoveClaims(statementIds, editAsBot, revisionId, summary, tags);
return new EditingResult(getRevisionIdFromResponse(response));
}
}
}
Expand All @@ -587,9 +590,9 @@ public void editEntityDocument(
MonolingualTextValue label = typed.getLabels().getModified().values().stream().findFirst().get();
builder.updateLabels(TermUpdateBuilder.create().put(label).build());
if (builder.build().equals(update)) {
wbEditingAction.wbSetLabel(update.getEntityId().getId(), null, null, null,
JsonNode response = wbEditingAction.wbSetLabel(update.getEntityId().getId(), null, null, null,
label.getLanguageCode(), label.getText(), editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
if (typed.getLabels().getRemoved().size() == 1) {
Expand All @@ -598,9 +601,9 @@ public void editEntityDocument(
String language = typed.getLabels().getRemoved().stream().findFirst().get();
builder.updateLabels(TermUpdateBuilder.create().remove(language).build());
if (builder.build().equals(update)) {
wbEditingAction.wbSetLabel(update.getEntityId().getId(), null, null, null,
JsonNode response = wbEditingAction.wbSetLabel(update.getEntityId().getId(), null, null, null,
language, null, editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
}
Expand All @@ -613,10 +616,10 @@ public void editEntityDocument(
.values().stream().findFirst().get();
builder.updateDescriptions(TermUpdateBuilder.create().put(description).build());
if (builder.build().equals(update)) {
wbEditingAction.wbSetDescription(update.getEntityId().getId(), null, null, null,
JsonNode response = wbEditingAction.wbSetDescription(update.getEntityId().getId(), null, null, null,
description.getLanguageCode(), description.getText(),
editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
if (typed.getDescriptions().getRemoved().size() == 1) {
Expand All @@ -625,9 +628,9 @@ public void editEntityDocument(
String language = typed.getDescriptions().getRemoved().stream().findFirst().get();
builder.updateDescriptions(TermUpdateBuilder.create().remove(language).build());
if (builder.build().equals(update)) {
wbEditingAction.wbSetDescription(update.getEntityId().getId(), null, null, null,
JsonNode response = wbEditingAction.wbSetDescription(update.getEntityId().getId(), null, null, null,
language, null, editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
if (typed.getAliases().size() == 1) {
Expand All @@ -646,9 +649,9 @@ public void editEntityDocument(
List<String> recreated = aliases.getRecreated()
.map(l -> l.stream().map(a -> a.getText()).collect(toList()))
.orElse(null);
wbEditingAction.wbSetAliases(update.getEntityId().getId(), null, null, null,
JsonNode response = wbEditingAction.wbSetAliases(update.getEntityId().getId(), null, null, null,
language, added, removed, recreated, editAsBot, revisionId, summary, tags);
return;
return new EditingResult(getRevisionIdFromResponse(response));
}
}
}
Expand All @@ -660,8 +663,7 @@ public void editEntityDocument(
SenseUpdate sense = typed.getUpdatedSenses().values().stream().findFirst().get();
builder.updateSense(sense);
if (builder.build().equals(update)) {
editEntityDocument(sense, false, summary, tags);
return;
return editEntityDocument(sense, false, summary, tags);
}
}
if (typed.getUpdatedForms().size() == 1) {
Expand All @@ -670,15 +672,15 @@ public void editEntityDocument(
FormUpdate form = typed.getUpdatedForms().values().stream().findFirst().get();
builder.updateForm(form);
if (builder.build().equals(update)) {
editEntityDocument(form, false, summary, tags);
return;
return editEntityDocument(form, false, summary, tags);
}
}
}
}
String data = JsonSerializer.getJsonString(update);
wbEditingAction.wbEditEntity(
EntityDocument document = wbEditingAction.wbEditEntity(
update.getEntityId().getId(), null, null, null, data, clear, editAsBot, revisionId, summary, tags);
return new EditingResult(document.getRevisionId());
}

/**
Expand Down Expand Up @@ -1131,4 +1133,29 @@ public <T extends EntityDocument> T nullEdit(T currentDocument)
JsonSerializer.getJsonString(update), false, editAsBot, currentDocument.getRevisionId(), null, null);
}

/**
* Extracts the last revision id from the JSON response returned
* by the API after an edit
*
* @param response
* the response as returned by Mediawiki
* @return
* the new revision id of the edited entity
* @throws JsonProcessingException
*/
protected long getRevisionIdFromResponse(JsonNode response) throws JsonProcessingException {
if(response == null) {
throw new MalformedResponseException("API response is null");
}
JsonNode entity = null;
if(response.has("entity")) {
entity = response.path("entity");
} else if(response.has("pageinfo")) {
entity = response.path("pageinfo");
}
if(entity != null && entity.has("lastrevid")) {
return entity.path("lastrevid").asLong();
}
throw new MalformedResponseException("The last revision id could not be found in API response");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.wikidata.wdtk.wikibaseapi;

/*-
* #%L
* Wikidata Toolkit Wikibase API
* %%
* Copyright (C) 2014 - 2023 Wikidata Toolkit Developers
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import static org.junit.Assert.assertEquals;

import java.util.OptionalLong;

import org.junit.Test;

public class EditingResultTest {

@Test
public void testGetRevisionId() {
EditingResult SUT = new EditingResult(1234L);

assertEquals(SUT.getLastRevisionId(), OptionalLong.of(1234L));
}

@Test
public void testNoRevisionId() {
EditingResult SUT = new EditingResult(0L);

assertEquals(SUT.getLastRevisionId(), OptionalLong.empty());
}
}
Loading

0 comments on commit 6205a38

Please sign in to comment.