diff --git a/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizer.java b/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizer.java index 1e153a493..51ee47277 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizer.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizer.java @@ -23,16 +23,19 @@ ******************************************************************************/ package org.openrefine.wikidata.qa.scrutinizers; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - import org.openrefine.wikidata.qa.QAWarning; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue; +import org.wikidata.wdtk.datamodel.interfaces.SnakGroup; import org.wikidata.wdtk.datamodel.interfaces.Statement; +import org.wikidata.wdtk.datamodel.interfaces.Value; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** * A scrutinizer that checks the compatibility of the qualifiers and the @@ -44,6 +47,42 @@ public class QualifierCompatibilityScrutinizer extends StatementScrutinizer { public static final String missingMandatoryQualifiersType = "missing-mandatory-qualifiers"; public static final String disallowedQualifiersType = "disallowed-qualifiers"; + public static String ALLOWED_QUALIFIERS_CONSTRAINT_QID = "Q21510851"; + public static String ALLOWED_QUALIFIERS_CONSTRAINT_PID = "P2306"; + + public static String MANDATORY_QUALIFIERS_CONSTRAINT_QID = "Q21510856"; + public static String MANDATORY_QUALIFIERS_CONSTRAINT_PID = "P2306"; + + class AllowedQualifierConstraint { + Set allowedProperties; + AllowedQualifierConstraint(Statement statement) { + allowedProperties = new HashSet<>(); + List specs = statement.getClaim().getQualifiers(); + if (specs != null) { + List properties = _fetcher.findValues(specs, ALLOWED_QUALIFIERS_CONSTRAINT_PID); + allowedProperties = properties.stream() + .filter(e -> e != null) + .map(e -> (PropertyIdValue) e) + .collect(Collectors.toSet()); + } + + } + } + + class MandatoryQualifierConstraint { + Set mandatoryProperties; + MandatoryQualifierConstraint(Statement statement) { + mandatoryProperties = new HashSet<>(); + List specs = statement.getClaim().getQualifiers(); + if (specs != null) { + List properties = _fetcher.findValues(specs, MANDATORY_QUALIFIERS_CONSTRAINT_PID); + mandatoryProperties = properties.stream() + .filter(e -> e != null) + .map(e -> (PropertyIdValue) e) + .collect(Collectors.toSet()); + } + } + } private Map> _allowedQualifiers; private Map> _mandatoryQualifiers; @@ -58,7 +97,11 @@ public class QualifierCompatibilityScrutinizer extends StatementScrutinizer { if (_allowedQualifiers.containsKey(statementProperty)) { allowed = _allowedQualifiers.get(statementProperty); } else { - allowed = _fetcher.allowedQualifiers(statementProperty); + List statementList = _fetcher.getConstraintsByType(statementProperty, ALLOWED_QUALIFIERS_CONSTRAINT_QID); + if (!statementList.isEmpty()){ + AllowedQualifierConstraint allowedQualifierConstraint = new AllowedQualifierConstraint(statementList.get(0)); + allowed = allowedQualifierConstraint.allowedProperties; + } _allowedQualifiers.put(statementProperty, allowed); } return allowed == null || allowed.contains(qualifierProperty); @@ -69,7 +112,11 @@ public class QualifierCompatibilityScrutinizer extends StatementScrutinizer { if (_mandatoryQualifiers.containsKey(statementProperty)) { mandatory = _mandatoryQualifiers.get(statementProperty); } else { - mandatory = _fetcher.mandatoryQualifiers(statementProperty); + List statementList = _fetcher.getConstraintsByType(statementProperty, MANDATORY_QUALIFIERS_CONSTRAINT_QID); + if (!statementList.isEmpty()){ + MandatoryQualifierConstraint mandatoryQualifierConstraint = new MandatoryQualifierConstraint(statementList.get(0)); + mandatory = mandatoryQualifierConstraint.mandatoryProperties; + } if (mandatory == null) { mandatory = new HashSet<>(); } diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizerTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizerTest.java index 1e9ccbe1f..8eb64ecaf 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizerTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/QualifierCompatibilityScrutinizerTest.java @@ -23,26 +23,39 @@ ******************************************************************************/ package org.openrefine.wikidata.qa.scrutinizers; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.openrefine.wikidata.qa.MockConstraintFetcher; +import org.openrefine.wikidata.qa.ConstraintFetcher; import org.openrefine.wikidata.testing.TestingData; +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.PropertyIdValue; 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 java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class QualifierCompatibilityScrutinizerTest extends StatementScrutinizerTest { - private Snak disallowedQualifier = Datamodel.makeNoValueSnak(MockConstraintFetcher.qualifierPid); - private Snak mandatoryQualifier = Datamodel.makeNoValueSnak(MockConstraintFetcher.mandatoryQualifierPid); - private Snak allowedQualifier = Datamodel.makeNoValueSnak(MockConstraintFetcher.allowedQualifierPid); + public static ItemIdValue allowedQualifierEntity = Datamodel.makeWikidataItemIdValue("Q21510851"); + public static ItemIdValue mandatoryQualifierEntity = Datamodel.makeWikidataItemIdValue("Q21510856"); + public static PropertyIdValue propertyParameterPID = Datamodel.makeWikidataPropertyIdValue("P2306"); + public static PropertyIdValue propertyParameterValue = Datamodel.makeWikidataPropertyIdValue("P585"); + + public static PropertyIdValue allowedPropertyIdValue = Datamodel.makeWikidataPropertyIdValue("P2196"); + public static PropertyIdValue mandatoryPropertyIdValue = Datamodel.makeWikidataPropertyIdValue("P2196"); + public static PropertyIdValue qualifierProperty = Datamodel.makeWikidataPropertyIdValue("P585"); + public static PropertyIdValue disallowedQualifierProperty = Datamodel.makeWikidataPropertyIdValue("P586"); @Override public EditScrutinizer getScrutinizer() { @@ -51,26 +64,75 @@ public class QualifierCompatibilityScrutinizerTest extends StatementScrutinizerT @Test public void testDisallowedQualifier() { + ItemIdValue idA = TestingData.existingId; + Snak mainSnak = Datamodel.makeSomeValueSnak(allowedPropertyIdValue); + Snak qualifierSnak = Datamodel.makeSomeValueSnak(disallowedQualifierProperty); + Statement statement = makeStatement(mainSnak, qualifierSnak); + ItemUpdate update = new ItemUpdateBuilder(idA).addStatement(statement).build(); - scrutinize(makeStatement(disallowedQualifier, mandatoryQualifier)); + Snak snak1 = Datamodel.makeValueSnak(propertyParameterPID, propertyParameterValue); + List snakList1 = Collections.singletonList(snak1); + SnakGroup snakGroup1 = Datamodel.makeSnakGroup(snakList1); + List snakGroupList = Collections.singletonList(snakGroup1); + List statementList = constraintParameterStatementList(allowedQualifierEntity, snakGroupList); + + ConstraintFetcher fetcher = mock(ConstraintFetcher.class); + when(fetcher.getConstraintsByType(allowedPropertyIdValue, "Q21510851")).thenReturn(statementList); + when(fetcher.findValues(snakGroupList, "P2306")).thenReturn(Collections.singletonList(qualifierProperty)); + setFetcher(fetcher); + + scrutinize(update); assertWarningsRaised(QualifierCompatibilityScrutinizer.disallowedQualifiersType); } @Test public void testMissingQualifier() { - scrutinize(makeStatement()); + ItemIdValue idA = TestingData.existingId; + Snak mainSnak = Datamodel.makeSomeValueSnak(mandatoryPropertyIdValue); + Statement statement = makeStatement(mainSnak); + ItemUpdate update = new ItemUpdateBuilder(idA).addStatement(statement).build(); + + Snak snak1 = Datamodel.makeValueSnak(propertyParameterPID, propertyParameterValue); + List snakList1 = Collections.singletonList(snak1); + SnakGroup snakGroup1 = Datamodel.makeSnakGroup(snakList1); + List snakGroupList = Collections.singletonList(snakGroup1); + List statementList = constraintParameterStatementList(mandatoryQualifierEntity, snakGroupList); + + ConstraintFetcher fetcher = mock(ConstraintFetcher.class); + when(fetcher.getConstraintsByType(mandatoryPropertyIdValue, "Q21510856")).thenReturn(statementList); + when(fetcher.findValues(snakGroupList, "P2306")).thenReturn(Collections.singletonList(qualifierProperty)); + setFetcher(fetcher); + + scrutinize(update); assertWarningsRaised(QualifierCompatibilityScrutinizer.missingMandatoryQualifiersType); } @Test public void testGoodEdit() { - scrutinize(makeStatement(allowedQualifier, mandatoryQualifier)); + ItemIdValue idA = TestingData.existingId; + Snak mainSnak = Datamodel.makeSomeValueSnak(allowedPropertyIdValue); + Snak qualifierSnak = Datamodel.makeSomeValueSnak(qualifierProperty); + Statement statement = makeStatement(mainSnak, qualifierSnak); + ItemUpdate update = new ItemUpdateBuilder(idA).addStatement(statement).build(); + + Snak snak1 = Datamodel.makeValueSnak(propertyParameterPID, propertyParameterValue); + List snakList1 = Collections.singletonList(snak1); + SnakGroup snakGroup1 = Datamodel.makeSnakGroup(snakList1); + List snakGroupList = Collections.singletonList(snakGroup1); + List statementList = constraintParameterStatementList(allowedQualifierEntity, snakGroupList); + + ConstraintFetcher fetcher = mock(ConstraintFetcher.class); + when(fetcher.getConstraintsByType(allowedPropertyIdValue, "Q21510851")).thenReturn(statementList); + when(fetcher.findValues(snakGroupList, "P2306")).thenReturn(Collections.singletonList(qualifierProperty)); + setFetcher(fetcher); + + scrutinize(update); assertNoWarningRaised(); } - private Statement makeStatement(Snak... qualifiers) { + private Statement makeStatement(Snak mainSnak, Snak... qualifiers) { Claim claim = Datamodel.makeClaim(TestingData.existingId, - Datamodel.makeNoValueSnak(MockConstraintFetcher.mainSnakPid), makeQualifiers(qualifiers)); + mainSnak, makeQualifiers(qualifiers)); return Datamodel.makeStatement(claim, Collections.emptyList(), StatementRank.NORMAL, ""); }