Migrate to new scope constraint format

This commit is contained in:
Antonin Delpeuch 2018-06-15 10:54:26 +01:00
parent dc6573d17b
commit bbc5936da6
5 changed files with 56 additions and 85 deletions

View File

@ -55,19 +55,19 @@ public interface ConstraintFetcher {
PropertyIdValue getInversePid(PropertyIdValue pid); PropertyIdValue getInversePid(PropertyIdValue pid);
/** /**
* Is this property for values only? * Can this property be used as values?
*/ */
boolean isForValuesOnly(PropertyIdValue pid); boolean allowedAsValue(PropertyIdValue pid);
/** /**
* Is this property for qualifiers only? * Can this property be used as qualifiers?
*/ */
boolean isForQualifiersOnly(PropertyIdValue pid); boolean allowedAsQualifier(PropertyIdValue pid);
/** /**
* Is this property for references only? * Can this property be used in a reference?
*/ */
boolean isForReferencesOnly(PropertyIdValue pid); boolean allowedAsReference(PropertyIdValue pid);
/** /**
* Get the list of allowed qualifiers (as property ids) for this property (null * Get the list of allowed qualifiers (as property ids) for this property (null

View File

@ -30,7 +30,9 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.openrefine.wikidata.utils.EntityCache; import org.openrefine.wikidata.utils.EntityCache;
import org.wikidata.wdtk.datamodel.helpers.Datamodel;
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.PropertyDocument; import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue; import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
import org.wikidata.wdtk.datamodel.interfaces.Snak; import org.wikidata.wdtk.datamodel.interfaces.Snak;
@ -57,7 +59,11 @@ public class WikidataConstraintFetcher implements ConstraintFetcher {
public static String INVERSE_CONSTRAINT_QID = "Q21510855"; public static String INVERSE_CONSTRAINT_QID = "Q21510855";
public static String INVERSE_PROPERTY_PID = "P2306"; public static String INVERSE_PROPERTY_PID = "P2306";
public static String USED_ONLY_AS_VALUES_CONSTRAINT_QID = "Q21528958"; public static String SCOPE_CONSTRAINT_QID = "Q53869507";
public static String SCOPE_CONSTRAINT_PID = "P5314";
public static String SCOPE_CONSTRAINT_VALUE_QID = "Q54828448";
public static String SCOPE_CONSTRAINT_QUALIFIER_QID = "Q54828449";
public static String SCOPE_CONSTRAINT_REFERENCE_QID = "Q54828450";
public static String USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID = "Q21510863"; public static String USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID = "Q21510863";
@ -102,18 +108,36 @@ public class WikidataConstraintFetcher implements ConstraintFetcher {
} }
@Override @Override
public boolean isForValuesOnly(PropertyIdValue pid) { public boolean allowedAsValue(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_VALUES_CONSTRAINT_QID) != null; List<SnakGroup> specs = getSingleConstraint(pid, SCOPE_CONSTRAINT_QID);
if (specs != null) {
ItemIdValue target = Datamodel.makeWikidataItemIdValue(SCOPE_CONSTRAINT_VALUE_QID);
return findValues(specs, SCOPE_CONSTRAINT_PID).contains(target);
}
return true;
} }
@Override @Override
public boolean isForQualifiersOnly(PropertyIdValue pid) { public boolean allowedAsQualifier(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID) != null; List<SnakGroup> specs = getSingleConstraint(pid, SCOPE_CONSTRAINT_QID);
if (specs != null) {
ItemIdValue target = Datamodel.makeWikidataItemIdValue(SCOPE_CONSTRAINT_QUALIFIER_QID);
return findValues(specs, SCOPE_CONSTRAINT_PID).contains(target);
}
return true;
} }
@Override @Override
public boolean isForReferencesOnly(PropertyIdValue pid) { public boolean allowedAsReference(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_REFERENCE_CONSTRAINT_QID) != null; List<SnakGroup> specs = getSingleConstraint(pid, SCOPE_CONSTRAINT_QID);
if (specs != null) {
ItemIdValue target = Datamodel.makeWikidataItemIdValue(SCOPE_CONSTRAINT_REFERENCE_QID);
return findValues(specs, SCOPE_CONSTRAINT_PID).contains(target);
}
return true;
} }
@Override @Override

View File

@ -23,11 +23,7 @@
******************************************************************************/ ******************************************************************************/
package org.openrefine.wikidata.qa.scrutinizers; package org.openrefine.wikidata.qa.scrutinizers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.openrefine.wikidata.qa.QAWarning; import org.openrefine.wikidata.qa.QAWarning;
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
@ -42,40 +38,6 @@ public class RestrictedPositionScrutinizer extends StatementScrutinizer {
MAINSNAK, QUALIFIER, REFERENCE MAINSNAK, QUALIFIER, REFERENCE
} }
private Map<PropertyIdValue, SnakPosition> _restrictedPids;
private Set<PropertyIdValue> _unrestrictedPids;
public RestrictedPositionScrutinizer() {
_restrictedPids = new HashMap<>();
_unrestrictedPids = new HashSet<>();
}
SnakPosition positionRestriction(PropertyIdValue 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 @Override
public void scrutinize(Statement statement, EntityIdValue entityId, boolean added) { public void scrutinize(Statement statement, EntityIdValue entityId, boolean added) {
// Skip the main snak // Skip the main snak
@ -99,16 +61,25 @@ public class RestrictedPositionScrutinizer extends StatementScrutinizer {
} }
public void scrutinize(Snak snak, EntityIdValue entityId, SnakPosition position, boolean added) { public void scrutinize(Snak snak, EntityIdValue entityId, SnakPosition position, boolean added) {
SnakPosition restriction = positionRestriction(snak.getPropertyId()); if (!positionAllowed(snak.getPropertyId(), position)) {
if (restriction != null && position != restriction) {
String positionStr = position.toString().toLowerCase(); String positionStr = position.toString().toLowerCase();
String restrictionStr = restriction.toString().toLowerCase();
QAWarning issue = new QAWarning("property-restricted-to-" + restrictionStr + "-found-in-" + positionStr, QAWarning issue = new QAWarning("property-found-in-" + positionStr,
snak.getPropertyId().getId(), QAWarning.Severity.IMPORTANT, 1); snak.getPropertyId().getId(), QAWarning.Severity.IMPORTANT, 1);
issue.setProperty("property_entity", snak.getPropertyId()); issue.setProperty("property_entity", snak.getPropertyId());
addIssue(issue); addIssue(issue);
} }
} }
public boolean positionAllowed(PropertyIdValue pid, SnakPosition position) {
if(position.equals(SnakPosition.MAINSNAK)) {
return _fetcher.allowedAsValue(pid);
} else if(position.equals(SnakPosition.QUALIFIER)) {
return _fetcher.allowedAsQualifier(pid);
} else if(position.equals(SnakPosition.REFERENCE)) {
return _fetcher.allowedAsReference(pid);
}
return true;
}
} }

View File

@ -60,18 +60,18 @@ public class MockConstraintFetcher implements ConstraintFetcher {
} }
@Override @Override
public boolean isForValuesOnly(PropertyIdValue pid) { public boolean allowedAsValue(PropertyIdValue pid) {
return mainSnakPid.equals(pid); return (!qualifierPid.equals(pid) && !referencePid.equals(pid));
} }
@Override @Override
public boolean isForQualifiersOnly(PropertyIdValue pid) { public boolean allowedAsQualifier(PropertyIdValue pid) {
return qualifierPid.equals(pid); return (!mainSnakPid.equals(pid) && !referencePid.equals(pid));
} }
@Override @Override
public boolean isForReferencesOnly(PropertyIdValue pid) { public boolean allowedAsReference(PropertyIdValue pid) {
return referencePid.equals(pid); return (!mainSnakPid.equals(pid) && !qualifierPid.equals(pid));
} }
@Override @Override

View File

@ -39,10 +39,7 @@ public class WikidataConstraintFetcherTests {
private PropertyIdValue endTime; private PropertyIdValue endTime;
private PropertyIdValue instanceOf; private PropertyIdValue instanceOf;
private PropertyIdValue gridId; private PropertyIdValue gridId;
private PropertyIdValue hasPart;
private PropertyIdValue partOf; private PropertyIdValue partOf;
private PropertyIdValue referenceURL;
private PropertyIdValue reasonForDeprecation;
private PropertyIdValue mother; private PropertyIdValue mother;
private PropertyIdValue child; private PropertyIdValue child;
@ -53,10 +50,7 @@ public class WikidataConstraintFetcherTests {
endTime = Datamodel.makeWikidataPropertyIdValue("P582"); endTime = Datamodel.makeWikidataPropertyIdValue("P582");
instanceOf = Datamodel.makeWikidataPropertyIdValue("P31"); instanceOf = Datamodel.makeWikidataPropertyIdValue("P31");
gridId = Datamodel.makeWikidataPropertyIdValue("P2427"); gridId = Datamodel.makeWikidataPropertyIdValue("P2427");
hasPart = Datamodel.makeWikidataPropertyIdValue("P527");
partOf = Datamodel.makeWikidataPropertyIdValue("P361"); partOf = Datamodel.makeWikidataPropertyIdValue("P361");
referenceURL = Datamodel.makeWikidataPropertyIdValue("P854");
reasonForDeprecation = Datamodel.makeWikidataPropertyIdValue("P2241");
mother = Datamodel.makeWikidataPropertyIdValue("P25"); mother = Datamodel.makeWikidataPropertyIdValue("P25");
child = Datamodel.makeWikidataPropertyIdValue("P40"); child = Datamodel.makeWikidataPropertyIdValue("P40");
} }
@ -77,24 +71,6 @@ public class WikidataConstraintFetcherTests {
Assert.assertEquals(fetcher.getInversePid(mother), child); Assert.assertEquals(fetcher.getInversePid(mother), child);
} }
@Test
public void testOnlyReferences() {
Assert.assertTrue(fetcher.isForReferencesOnly(referenceURL));
Assert.assertFalse(fetcher.isForReferencesOnly(reasonForDeprecation));
}
@Test
public void testOnlyQualifiers() {
Assert.assertTrue(fetcher.isForQualifiersOnly(reasonForDeprecation));
Assert.assertFalse(fetcher.isForQualifiersOnly(headOfGovernment));
}
@Test
public void testOnlyValues() {
Assert.assertTrue(fetcher.isForValuesOnly(headOfGovernment));
Assert.assertFalse(fetcher.isForValuesOnly(referenceURL));
}
@Test @Test
public void testAllowedQualifiers() { public void testAllowedQualifiers() {
Assert.assertTrue(fetcher.allowedQualifiers(headOfGovernment).contains(startTime)); Assert.assertTrue(fetcher.allowedQualifiers(headOfGovernment).contains(startTime));