diff --git a/.gitignore b/.gitignore index 9c0e0eb49..c1e50198c 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ test-out/ open-refine.log .vscode +.idea +*.iml + main/target/ main/webapp/WEB-INF/lib/ server/target/ diff --git a/extensions/wikidata/src/org/openrefine/wikidata/exporters/QuickStatementsExporter.java b/extensions/wikidata/src/org/openrefine/wikidata/exporters/QuickStatementsExporter.java index 4a6fdf1ae..a13f1a20e 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/exporters/QuickStatementsExporter.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/exporters/QuickStatementsExporter.java @@ -151,21 +151,38 @@ public class QuickStatementsExporter implements WriterExporter { Value val = claim.getValue(); ValueVisitor vv = new QSValuePrinter(); String targetValue = val.accept(vv); - if (targetValue != null) { + if (targetValue != null) { // issue #2320 if (!add) { + // According to: https://www.wikidata.org/wiki/Help:QuickStatements#Removing_statements, + // Removing statements won't be followed by qualifiers or references. writer.write("- "); - } - writer.write(qid + "\t" + pid + "\t" + targetValue); - for (SnakGroup q : claim.getQualifiers()) { - translateSnakGroup(q, false, writer); - } - for (Reference r : statement.getReferences()) { - for (SnakGroup g : r.getSnakGroups()) { - translateSnakGroup(g, true, writer); + writer.write(qid + "\t" + pid + "\t" + targetValue); + writer.write("\n"); + } else { // add statements + if (statement.getReferences().isEmpty()) { + writer.write(qid + "\t" + pid + "\t" + targetValue); + for (SnakGroup q : claim.getQualifiers()) { + translateSnakGroup(q, false, writer); + } + writer.write("\n"); + } else { + // According to: https://www.wikidata.org/wiki/Help:QuickStatements#Add_statement_with_sources + // Existing statements with an exact match (property and value) will not be added again; + // however additional references might be added to the statement. + + // So, to handle multiple references, we can duplicate the statement just with different references. + for (Reference r : statement.getReferences()) { + writer.write(qid + "\t" + pid + "\t" + targetValue); + for (SnakGroup q : claim.getQualifiers()) { + translateSnakGroup(q, false, writer); + } + for (SnakGroup g : r.getSnakGroups()) { + translateSnakGroup(g, true, writer); + } + writer.write("\n"); + } } - break; // QS only supports one reference } - writer.write("\n"); } } diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/exporters/QuickStatementsExporterTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/exporters/QuickStatementsExporterTest.java index d7350681c..8f74729ab 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/exporters/QuickStatementsExporterTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/exporters/QuickStatementsExporterTest.java @@ -38,12 +38,7 @@ import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdateBuilder; import org.testng.annotations.Test; import org.wikidata.wdtk.datamodel.helpers.Datamodel; -import org.wikidata.wdtk.datamodel.interfaces.Claim; -import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue; -import org.wikidata.wdtk.datamodel.interfaces.Snak; -import org.wikidata.wdtk.datamodel.interfaces.SnakGroup; -import org.wikidata.wdtk.datamodel.interfaces.Statement; -import org.wikidata.wdtk.datamodel.interfaces.StatementRank; +import org.wikidata.wdtk.datamodel.interfaces.*; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; @@ -139,6 +134,35 @@ public class QuickStatementsExporterTest extends WikidataRefineTest { assertEquals("Q1377\tP38\tQ865528\tP38\tQ1377\n", export(update)); } + /** + * issue #2320 + * + * A statement with different references should be duplicated, + * but each with a different reference. + */ + @Test + public void testReferences() + throws IOException { + Statement baseStatement = TestingData.generateStatement(qid1, qid2); + Statement otherStatement = TestingData.generateStatement(qid2, qid1); + + Snak snak1 = baseStatement.getClaim().getMainSnak(); + Snak snak2 = otherStatement.getClaim().getMainSnak(); + SnakGroup group1 = Datamodel.makeSnakGroup(Collections.singletonList(snak1)); + SnakGroup group2 = Datamodel.makeSnakGroup(Collections.singletonList(snak2)); + Claim claim = Datamodel.makeClaim(qid1, baseStatement.getClaim().getMainSnak(), + Collections.singletonList(group2)); + + Reference reference1 = Datamodel.makeReference(Collections.singletonList(group1)); + Reference reference2 = Datamodel.makeReference(Collections.singletonList(group2)); + + Statement statement = Datamodel.makeStatement(claim, Arrays.asList(reference1, reference2), StatementRank.NORMAL, ""); + ItemUpdate update = new ItemUpdateBuilder(qid1).addStatement(statement).build(); + + assertEquals("Q1377\tP38\tQ865528\tP38\tQ1377\tS38\tQ865528\n" + + "Q1377\tP38\tQ865528\tP38\tQ1377\tS38\tQ1377\n", export(update)); + } + @Test public void testNoSchema() throws IOException {