Merge pull request #1655 from OpenRefine/new-scope-constraint

Migrate to new scope constraint format
This commit is contained in:
Antonin Delpeuch 2018-06-22 12:22:08 +02:00 committed by GitHub
commit b3ee80d504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 105 deletions

View File

@ -121,29 +121,17 @@
"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": {
"property-found-in-mainsnak": {
"title": "{property_entity} used as statement.",
"body": "You are using {property_entity} in a statement but it is designed to be used in references only."
"body": "You are using {property_entity} as a main statement but it is not designed for that."
},
"property-restricted-to-reference-found-in-qualifier": {
"property-found-in-qualifier": {
"title": "{property_entity} used as qualifier.",
"body": "You are using in {property_entity} in a qualifier but it is designed to be used in references only."
"body": "You are using in {property_entity} as a qualifier but it is not designed for that ."
},
"property-restricted-to-qualifier-found-in-mainsnak": {
"title": "{property_entity} used as statement.",
"body": "You are using {property_entity} in a statement but it is designed to be used in qualifiers only."
},
"property-restricted-to-qualifier-found-in-reference": {
"property-found-in-reference": {
"title": "{property_entity} used as reference.",
"body": "You are using {property_entity} in a reference but it is designed to be used in qualifiers only."
},
"property-restricted-to-mainsnak-found-in-qualifier": {
"title": "{property_entity} used as qualifier.",
"body": "You are using {property_entity} in a qualifier but it is designed to be used as a statement only."
},
"property-restricted-to-mainsnak-found-in-reference": {
"title": "{property_entity} used as reference.",
"body": "You are using {property_entity} in a reference but it is designed to be used as a statement only."
"body": "You are using {property_entity} in a reference but it is not designed for that."
},
"missing-mandatory-qualifiers": {
"title": "{statement_property_entity} is missing a {missing_property_entity} qualifier.",

View File

@ -62,19 +62,19 @@ public interface ConstraintFetcher {
boolean isSymmetric(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

View File

@ -60,7 +60,11 @@ public class WikidataConstraintFetcher implements ConstraintFetcher {
public static String INVERSE_PROPERTY_PID = "P2306";
public static String SYMMETRIC_CONSTRAINT_QID = "Q21510862";
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";
@ -123,18 +127,36 @@ public class WikidataConstraintFetcher implements ConstraintFetcher {
}
@Override
public boolean isForValuesOnly(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_VALUES_CONSTRAINT_QID) != null;
public boolean allowedAsValue(PropertyIdValue pid) {
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
public boolean isForQualifiersOnly(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_QUALIFIER_CONSTRAINT_QID) != null;
public boolean allowedAsQualifier(PropertyIdValue pid) {
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
public boolean isForReferencesOnly(PropertyIdValue pid) {
return getSingleConstraint(pid, USED_ONLY_AS_REFERENCE_CONSTRAINT_QID) != null;
public boolean allowedAsReference(PropertyIdValue pid) {
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

View File

@ -23,11 +23,7 @@
******************************************************************************/
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.QAWarning;
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
@ -42,40 +38,6 @@ public class RestrictedPositionScrutinizer extends StatementScrutinizer {
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
public void scrutinize(Statement statement, EntityIdValue entityId, boolean added) {
// Skip the main snak
@ -99,16 +61,25 @@ public class RestrictedPositionScrutinizer extends StatementScrutinizer {
}
public void scrutinize(Snak snak, EntityIdValue entityId, SnakPosition position, boolean added) {
SnakPosition restriction = positionRestriction(snak.getPropertyId());
if (restriction != null && position != restriction) {
if (!positionAllowed(snak.getPropertyId(), position)) {
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);
issue.setProperty("property_entity", snak.getPropertyId());
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

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

View File

@ -39,10 +39,7 @@ public class WikidataConstraintFetcherTests {
private PropertyIdValue endTime;
private PropertyIdValue instanceOf;
private PropertyIdValue gridId;
private PropertyIdValue hasPart;
private PropertyIdValue partOf;
private PropertyIdValue referenceURL;
private PropertyIdValue reasonForDeprecation;
private PropertyIdValue mother;
private PropertyIdValue child;
@ -53,10 +50,7 @@ public class WikidataConstraintFetcherTests {
endTime = Datamodel.makeWikidataPropertyIdValue("P582");
instanceOf = Datamodel.makeWikidataPropertyIdValue("P31");
gridId = Datamodel.makeWikidataPropertyIdValue("P2427");
hasPart = Datamodel.makeWikidataPropertyIdValue("P527");
partOf = Datamodel.makeWikidataPropertyIdValue("P361");
referenceURL = Datamodel.makeWikidataPropertyIdValue("P854");
reasonForDeprecation = Datamodel.makeWikidataPropertyIdValue("P2241");
mother = Datamodel.makeWikidataPropertyIdValue("P25");
child = Datamodel.makeWikidataPropertyIdValue("P40");
}
@ -77,24 +71,6 @@ public class WikidataConstraintFetcherTests {
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
public void testAllowedQualifiers() {
Assert.assertTrue(fetcher.allowedQualifiers(headOfGovernment).contains(startTime));

View File

@ -48,7 +48,7 @@ public class RestrictedPositionScrutinizerTest extends SnakScrutinizerTest {
@Test
public void testTriggerMainSnak() {
scrutinize(TestingData.generateStatement(qid, MockConstraintFetcher.qualifierPid, qid));
assertWarningsRaised("property-restricted-to-qualifier-found-in-mainsnak");
assertWarningsRaised("property-found-in-mainsnak");
}
@Test
@ -72,7 +72,7 @@ public class RestrictedPositionScrutinizerTest extends SnakScrutinizerTest {
TestingData.generateStatement(qid, MockConstraintFetcher.mainSnakPid, qid).getClaim(),
Collections.singletonList(Datamodel.makeReference(snakGroups)), StatementRank.NORMAL, "");
scrutinize(statement);
assertWarningsRaised("property-restricted-to-mainsnak-found-in-reference");
assertWarningsRaised("property-found-in-reference");
}
}