Add scrutinizer for allowed and mandatory qualifiers
This commit is contained in:
parent
283661956b
commit
316ee86e1a
@ -77,6 +77,14 @@
|
|||||||
"property-restricted-to-mainsnak-found-in-reference": {
|
"property-restricted-to-mainsnak-found-in-reference": {
|
||||||
"title": "Statement-only property used as reference.",
|
"title": "Statement-only property used as reference.",
|
||||||
"body": "You are using in a reference a property that was designed to be used as a statement only."
|
"body": "You are using in a reference a property that was designed to be used as a statement only."
|
||||||
|
},
|
||||||
|
"missing-mandatory-qualifiers": {
|
||||||
|
"title": "Missing mandatory qualifiers.",
|
||||||
|
"body": "Your statements are missing qualifiers, it would be good to add them."
|
||||||
|
},
|
||||||
|
"disallowed-qualifiers": {
|
||||||
|
"title": "Disallowed qualifiers.",
|
||||||
|
"body": "Some of your qualifiers are incompatible with the statements that they qualify. Please check your schema."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package org.openrefine.wikidata.qa;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -11,6 +12,7 @@ import org.wikidata.wdtk.datamodel.interfaces.EntityDocument;
|
|||||||
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
|
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
|
||||||
import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
|
import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
|
||||||
import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
|
import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
|
||||||
import org.wikidata.wdtk.datamodel.interfaces.Snak;
|
import org.wikidata.wdtk.datamodel.interfaces.Snak;
|
||||||
import org.wikidata.wdtk.datamodel.interfaces.SnakGroup;
|
import org.wikidata.wdtk.datamodel.interfaces.SnakGroup;
|
||||||
import org.wikidata.wdtk.datamodel.interfaces.Statement;
|
import org.wikidata.wdtk.datamodel.interfaces.Statement;
|
||||||
@ -42,8 +44,8 @@ public class ConstraintFetcher {
|
|||||||
|
|
||||||
// The following constraints still need to be implemented:
|
// The following constraints still need to be implemented:
|
||||||
|
|
||||||
public static String ALLOWED_QUALIFIERS_CONSRAINT_QID = "Q21510851";
|
public static String ALLOWED_QUALIFIERS_CONSTRAINT_QID = "Q21510851";
|
||||||
public static String ALLOWED_QUALIFIERS_PID = "P2306";
|
public static String ALLOWED_QUALIFIERS_CONSTRAINT_PID = "P2306";
|
||||||
|
|
||||||
public static String MANDATORY_QUALIFIERS_CONSTRAINT_QID = "Q21510856";
|
public static String MANDATORY_QUALIFIERS_CONSTRAINT_QID = "Q21510856";
|
||||||
public static String MANDATORY_QUALIFIERS_CONSTRAINT_PID = "P2306";
|
public static String MANDATORY_QUALIFIERS_CONSTRAINT_PID = "P2306";
|
||||||
@ -108,6 +110,32 @@ public class ConstraintFetcher {
|
|||||||
return getSingleConstraint(pid, USED_ONLY_AS_REFERENCE_CONSTRAINT_QID) != null;
|
return getSingleConstraint(pid, USED_ONLY_AS_REFERENCE_CONSTRAINT_QID) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of allowed qualifiers (as property ids) for this property (null if any)
|
||||||
|
*/
|
||||||
|
public Set<PropertyIdValue> allowedQualifiers(PropertyIdValue pid) {
|
||||||
|
List<SnakGroup> specs = getSingleConstraint(pid.getId(), ALLOWED_QUALIFIERS_CONSTRAINT_QID);
|
||||||
|
|
||||||
|
if (specs != null) {
|
||||||
|
List<Value> properties = findValues(specs, ALLOWED_QUALIFIERS_CONSTRAINT_PID);
|
||||||
|
return properties.stream().map(e -> (PropertyIdValue) e).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of mandatory qualifiers (as property ids) for this property (null if any)
|
||||||
|
*/
|
||||||
|
public Set<PropertyIdValue> mandatoryQualifiers(PropertyIdValue pid) {
|
||||||
|
List<SnakGroup> specs = getSingleConstraint(pid.getId(), MANDATORY_QUALIFIERS_CONSTRAINT_QID);
|
||||||
|
|
||||||
|
if (specs != null) {
|
||||||
|
List<Value> properties = findValues(specs, MANDATORY_QUALIFIERS_CONSTRAINT_PID);
|
||||||
|
return properties.stream().map(e -> (PropertyIdValue) e).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a single constraint for a particular type and a property, or null
|
* Returns a single constraint for a particular type and a property, or null
|
||||||
* if there is no such constraint
|
* if there is no such constraint
|
||||||
|
@ -8,6 +8,7 @@ import org.openrefine.wikidata.qa.scrutinizers.EditScrutinizer;
|
|||||||
import org.openrefine.wikidata.qa.scrutinizers.FormatConstraintScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.FormatConstraintScrutinizer;
|
||||||
import org.openrefine.wikidata.qa.scrutinizers.InverseConstraintScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.InverseConstraintScrutinizer;
|
||||||
import org.openrefine.wikidata.qa.scrutinizers.NewItemScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.NewItemScrutinizer;
|
||||||
|
import org.openrefine.wikidata.qa.scrutinizers.QualifierCompatibilityScrutinizer;
|
||||||
import org.openrefine.wikidata.qa.scrutinizers.RestrictedPositionScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.RestrictedPositionScrutinizer;
|
||||||
import org.openrefine.wikidata.qa.scrutinizers.SelfReferentialScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.SelfReferentialScrutinizer;
|
||||||
import org.openrefine.wikidata.qa.scrutinizers.UnsourcedScrutinizer;
|
import org.openrefine.wikidata.qa.scrutinizers.UnsourcedScrutinizer;
|
||||||
@ -33,6 +34,7 @@ public class EditInspector {
|
|||||||
register(new SelfReferentialScrutinizer());
|
register(new SelfReferentialScrutinizer());
|
||||||
register(new UnsourcedScrutinizer());
|
register(new UnsourcedScrutinizer());
|
||||||
register(new RestrictedPositionScrutinizer());
|
register(new RestrictedPositionScrutinizer());
|
||||||
|
register(new QualifierCompatibilityScrutinizer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
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.ConstraintFetcher;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.Statement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scrutinizer that checks the compatibility of the qualifiers
|
||||||
|
* and the property of a statement, and looks for mandatory qualifiers.
|
||||||
|
* @author antonin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class QualifierCompatibilityScrutinizer extends StatementScrutinizer {
|
||||||
|
|
||||||
|
private ConstraintFetcher _fetcher;
|
||||||
|
private Map<PropertyIdValue, Set<PropertyIdValue>> _allowedQualifiers;
|
||||||
|
private Map<PropertyIdValue, Set<PropertyIdValue>> _mandatoryQualifiers;
|
||||||
|
|
||||||
|
public QualifierCompatibilityScrutinizer() {
|
||||||
|
_fetcher = new ConstraintFetcher();
|
||||||
|
_allowedQualifiers = new HashMap<>();
|
||||||
|
_mandatoryQualifiers = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean qualifierIsAllowed(PropertyIdValue statementProperty, PropertyIdValue qualifierProperty) {
|
||||||
|
Set<PropertyIdValue> allowed = null;
|
||||||
|
if (_allowedQualifiers.containsKey(statementProperty)) {
|
||||||
|
allowed = _allowedQualifiers.get(statementProperty);
|
||||||
|
} else {
|
||||||
|
allowed = _fetcher.allowedQualifiers(statementProperty);
|
||||||
|
_allowedQualifiers.put(statementProperty, allowed);
|
||||||
|
}
|
||||||
|
return allowed == null || allowed.contains(qualifierProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<PropertyIdValue> mandatoryQualifiers(PropertyIdValue statementProperty) {
|
||||||
|
Set<PropertyIdValue> mandatory = null;
|
||||||
|
if (_mandatoryQualifiers.containsKey(statementProperty)) {
|
||||||
|
mandatory = _mandatoryQualifiers.get(statementProperty);
|
||||||
|
} else {
|
||||||
|
mandatory = _fetcher.mandatoryQualifiers(statementProperty);
|
||||||
|
if (mandatory == null) {
|
||||||
|
mandatory = new HashSet<>();
|
||||||
|
}
|
||||||
|
_mandatoryQualifiers.put(statementProperty, mandatory);
|
||||||
|
}
|
||||||
|
return mandatory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scrutinize(Statement statement, EntityIdValue entityId, boolean added) {
|
||||||
|
PropertyIdValue statementProperty = statement.getClaim().getMainSnak().getPropertyId();
|
||||||
|
Set<PropertyIdValue> qualifiers = statement.getClaim().getQualifiers().
|
||||||
|
stream().map(e -> e.getProperty()).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Set<PropertyIdValue> missingQualifiers = mandatoryQualifiers(statementProperty)
|
||||||
|
.stream().filter(p -> !qualifiers.contains(p)).collect(Collectors.toSet());
|
||||||
|
Set<PropertyIdValue> disallowedQualifiers = qualifiers
|
||||||
|
.stream().filter(p -> !qualifierIsAllowed(statementProperty, p)).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if( !missingQualifiers.isEmpty()) {
|
||||||
|
warning("missing-mandatory-qualifiers");
|
||||||
|
}
|
||||||
|
if (!disallowedQualifiers.isEmpty()) {
|
||||||
|
warning("disallowed-qualifiers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,14 +2,24 @@ package org.openrefine.wikidata.qa;
|
|||||||
|
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
import org.wikidata.wdtk.datamodel.helpers.Datamodel;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ConstraintFetcherTests {
|
public class ConstraintFetcherTests {
|
||||||
|
|
||||||
private ConstraintFetcher fetcher;
|
private ConstraintFetcher fetcher;
|
||||||
|
|
||||||
|
private PropertyIdValue headOfGovernment;
|
||||||
|
private PropertyIdValue startTime;
|
||||||
|
private PropertyIdValue endTime;
|
||||||
|
|
||||||
public ConstraintFetcherTests() {
|
public ConstraintFetcherTests() {
|
||||||
fetcher = new ConstraintFetcher();
|
fetcher = new ConstraintFetcher();
|
||||||
|
headOfGovernment = Datamodel.makeWikidataPropertyIdValue("P6");
|
||||||
|
startTime = Datamodel.makeWikidataPropertyIdValue("P580");
|
||||||
|
endTime = Datamodel.makeWikidataPropertyIdValue("P582");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -45,4 +55,19 @@ public class ConstraintFetcherTests {
|
|||||||
Assert.assertTrue(fetcher.isForValuesOnly("P6"));
|
Assert.assertTrue(fetcher.isForValuesOnly("P6"));
|
||||||
Assert.assertFalse(fetcher.isForValuesOnly("P854"));
|
Assert.assertFalse(fetcher.isForValuesOnly("P854"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllowedQualifiers() {
|
||||||
|
Assert.assertTrue(fetcher.allowedQualifiers(headOfGovernment).contains(startTime));
|
||||||
|
Assert.assertTrue(fetcher.allowedQualifiers(headOfGovernment).contains(endTime));
|
||||||
|
Assert.assertFalse(fetcher.allowedQualifiers(headOfGovernment).contains(headOfGovernment));
|
||||||
|
Assert.assertNull(fetcher.allowedQualifiers(startTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMandatoryQualifiers() {
|
||||||
|
Assert.assertTrue(fetcher.mandatoryQualifiers(headOfGovernment).contains(startTime));
|
||||||
|
Assert.assertFalse(fetcher.mandatoryQualifiers(headOfGovernment).contains(endTime));
|
||||||
|
Assert.assertNull(fetcher.allowedQualifiers(startTime));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user