Add support for snak location constraints
This commit is contained in:
parent
142eeabfeb
commit
283661956b
@ -53,6 +53,30 @@
|
||||
"unsourced-statements": {
|
||||
"title": "Statements without references.",
|
||||
"body": "Most statements should have references. You can add them easily in the schema."
|
||||
},
|
||||
"property-restricted-to-reference-found-in-mainsnak": {
|
||||
"title": "Reference-only property used as statement.",
|
||||
"body": "You are using in a statement a property that was designed to be used in references only."
|
||||
},
|
||||
"property-restricted-to-reference-found-in-qualifier": {
|
||||
"title": "Reference-only property used as qualifier.",
|
||||
"body": "You are using in a qualifier a property that was designed to be used in references only."
|
||||
},
|
||||
"property-restricted-to-qualifier-found-in-mainsnak": {
|
||||
"title": "Qualifier-only property used as statement.",
|
||||
"body": "You are using in a statement a property that was designed to be used in qualifiers only."
|
||||
},
|
||||
"property-restricted-to-qualifier-found-in-reference": {
|
||||
"title": "Qualifier-only property used as reference.",
|
||||
"body": "You are using in a reference a property that was designed to be used in qualifiers only."
|
||||
},
|
||||
"property-restricted-to-mainsnak-found-in-qualifier": {
|
||||
"title": "Statement-only property used as qualifier.",
|
||||
"body": "You are using in a qualifier a property that was designed to be used as a statement only."
|
||||
},
|
||||
"property-restricted-to-mainsnak-found-in-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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,20 @@ public class ConstraintFetcher {
|
||||
public static String INVERSE_CONSTRAINT_QID = "Q21510855";
|
||||
public static String INVERSE_PROPERTY_PID = "P2306";
|
||||
|
||||
public static String USED_ONLY_AS_VALUES_CONSTRAINT_QID = "Q21528958";
|
||||
|
||||
public static String USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID = "Q21510863";
|
||||
|
||||
public static String USED_ONLY_AS_REFERENCE_CONSTRAINT_QID = "Q21528959";
|
||||
|
||||
// The following constraints still need to be implemented:
|
||||
|
||||
public static String ALLOWED_QUALIFIERS_CONSRAINT_QID = "Q21510851";
|
||||
public static String ALLOWED_QUALIFIERS_PID = "P2306";
|
||||
|
||||
public static String MANDATORY_QUALIFIERS_CONSTRAINT_QID = "Q21510856";
|
||||
public static String MANDATORY_QUALIFIERS_CONSTRAINT_PID = "P2306";
|
||||
|
||||
public static String SINGLE_VALUE_CONSRAINT_QID = "Q19474404";
|
||||
public static String DISTINCT_VALUES_CONSRAINT_QID = "Q21502410";
|
||||
public static String TYPE_CONSTRAINT_QID = "Q21503250";
|
||||
@ -73,6 +87,27 @@ public class ConstraintFetcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this property for values only?
|
||||
*/
|
||||
public boolean isForValuesOnly(String pid) {
|
||||
return getSingleConstraint(pid, USED_ONLY_AS_VALUES_CONSTRAINT_QID) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this property for qualifiers only?
|
||||
*/
|
||||
public boolean isForQualifiersOnly(String pid) {
|
||||
return getSingleConstraint(pid, USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this property for references only?
|
||||
*/
|
||||
public boolean isForReferencesOnly(String pid) {
|
||||
return getSingleConstraint(pid, USED_ONLY_AS_REFERENCE_CONSTRAINT_QID) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single constraint for a particular type and a property, or null
|
||||
* 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.InverseConstraintScrutinizer;
|
||||
import org.openrefine.wikidata.qa.scrutinizers.NewItemScrutinizer;
|
||||
import org.openrefine.wikidata.qa.scrutinizers.RestrictedPositionScrutinizer;
|
||||
import org.openrefine.wikidata.qa.scrutinizers.SelfReferentialScrutinizer;
|
||||
import org.openrefine.wikidata.qa.scrutinizers.UnsourcedScrutinizer;
|
||||
import org.openrefine.wikidata.schema.ItemUpdate;
|
||||
@ -31,6 +32,7 @@ public class EditInspector {
|
||||
register(new InverseConstraintScrutinizer());
|
||||
register(new SelfReferentialScrutinizer());
|
||||
register(new UnsourcedScrutinizer());
|
||||
register(new RestrictedPositionScrutinizer());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,90 @@
|
||||
package org.openrefine.wikidata.qa.scrutinizers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openrefine.wikidata.qa.ConstraintFetcher;
|
||||
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
|
||||
import org.wikidata.wdtk.datamodel.interfaces.Reference;
|
||||
import org.wikidata.wdtk.datamodel.interfaces.Snak;
|
||||
import org.wikidata.wdtk.datamodel.interfaces.Statement;
|
||||
|
||||
|
||||
public class RestrictedPositionScrutinizer extends StatementScrutinizer {
|
||||
|
||||
protected enum SnakPosition {
|
||||
MAINSNAK,
|
||||
QUALIFIER,
|
||||
REFERENCE
|
||||
}
|
||||
|
||||
private Map<String, SnakPosition> _restrictedPids;
|
||||
private Set<String> _unrestrictedPids;
|
||||
private ConstraintFetcher _fetcher;
|
||||
|
||||
public RestrictedPositionScrutinizer() {
|
||||
_restrictedPids = new HashMap<>();
|
||||
_unrestrictedPids = new HashSet<>();
|
||||
_fetcher = new ConstraintFetcher();
|
||||
}
|
||||
|
||||
SnakPosition positionRestriction(String pid) {
|
||||
if(_unrestrictedPids.contains(pid)) {
|
||||
return null;
|
||||
}
|
||||
SnakPosition restriction = _restrictedPids.get(pid);
|
||||
if (restriction != null) {
|
||||
return restriction;
|
||||
} else {
|
||||
if (_fetcher.isForValuesOnly(pid)) {
|
||||
restriction = SnakPosition.MAINSNAK;
|
||||
} else if (_fetcher.isForQualifiersOnly(pid)) {
|
||||
restriction = SnakPosition.QUALIFIER;
|
||||
} else if (_fetcher.isForReferencesOnly(pid)) {
|
||||
restriction = SnakPosition.REFERENCE;
|
||||
}
|
||||
|
||||
// Cache these results:
|
||||
if (restriction != null) {
|
||||
_restrictedPids.put(pid, restriction);
|
||||
} else {
|
||||
_unrestrictedPids.add(pid);
|
||||
}
|
||||
return restriction;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrutinize(Statement statement, EntityIdValue entityId, boolean added) {
|
||||
// Skip the main snak
|
||||
scrutinize(statement.getClaim().getMainSnak(), entityId, SnakPosition.MAINSNAK, added);
|
||||
|
||||
// Qualifiers
|
||||
scrutinizeSnakSet(statement.getClaim().getAllQualifiers(), entityId, SnakPosition.QUALIFIER, added);
|
||||
|
||||
// References
|
||||
for(Reference ref : statement.getReferences()) {
|
||||
scrutinizeSnakSet(ref.getAllSnaks(), entityId, SnakPosition.REFERENCE, added);
|
||||
}
|
||||
}
|
||||
|
||||
protected void scrutinizeSnakSet(Iterator<Snak> snaks, EntityIdValue entityId, SnakPosition position, boolean added) {
|
||||
while(snaks.hasNext()) {
|
||||
Snak snak = snaks.next();
|
||||
scrutinize(snak, entityId, position, added);
|
||||
}
|
||||
}
|
||||
|
||||
public void scrutinize(Snak snak, EntityIdValue entityId, SnakPosition position, boolean added) {
|
||||
SnakPosition restriction = positionRestriction(snak.getPropertyId().getId());
|
||||
if (restriction != null && position != restriction) {
|
||||
String positionStr = position.toString().toLowerCase();
|
||||
String restrictionStr = restriction.toString().toLowerCase();
|
||||
warning("property-restricted-to-"+restrictionStr+"-found-in-"+positionStr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,7 @@ public abstract class SnakScrutinizer extends StatementScrutinizer {
|
||||
}
|
||||
}
|
||||
|
||||
private void scrutinizeSnakSet(Iterator<Snak> snaks, EntityIdValue entityId, boolean added) {
|
||||
protected void scrutinizeSnakSet(Iterator<Snak> snaks, EntityIdValue entityId, boolean added) {
|
||||
while(snaks.hasNext()) {
|
||||
Snak snak = snaks.next();
|
||||
scrutinize(snak, entityId, added);
|
||||
|
@ -27,4 +27,22 @@ public class ConstraintFetcherTests {
|
||||
public void testGetInverseConstraint() {
|
||||
Assert.assertEquals(fetcher.getInversePid("P361"), "P527");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyReferences() {
|
||||
Assert.assertTrue(fetcher.isForReferencesOnly("P854"));
|
||||
Assert.assertFalse(fetcher.isForReferencesOnly("P2241"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyQualifiers() {
|
||||
Assert.assertTrue(fetcher.isForQualifiersOnly("P2241"));
|
||||
Assert.assertFalse(fetcher.isForQualifiersOnly("P6"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyValues() {
|
||||
Assert.assertTrue(fetcher.isForValuesOnly("P6"));
|
||||
Assert.assertFalse(fetcher.isForValuesOnly("P854"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user