Skip to content

Commit

Permalink
Add support for predicate_type.
Browse files Browse the repository at this point in the history
Recognise the `predicate_type` slot in mappings and mapping sets. Check
that it does not contain the illegal values `rdfs literal` and `composed
entity expression`.

Add a `predicate_type==` filter in SSSOM/T.

When producing OWL axioms from mappings in "direct" mode, use the value
of the `predicate_type` slot, if present, to determine the type of axiom
to generate.
  • Loading branch information
gouttegd committed Dec 20, 2024
1 parent 369d99a commit 59b5b78
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 2 deletions.
6 changes: 6 additions & 0 deletions core/src/main/java/org/incenp/obofoundry/sssom/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class Validator {
public static final String MISSING_OBJECT_ID = "Missing object_id";
public static final String MISSING_PREDICATE = "Missing predicate_id";
public static final String MISSING_JUSTIFICATION = "Missing mapping_justification";
public static final String INVALID_PREDICATE_TYPE = "Invalid predicate_type";

/**
* Validates an individual mapping. This method checks that the slots that are
Expand Down Expand Up @@ -75,6 +76,11 @@ public String validate(Mapping mapping) {
return MISSING_JUSTIFICATION;
}

if ( mapping.getPredicateType() == EntityType.RDFS_LITERAL
|| mapping.getPredicateType() == EntityType.COMPOSED_ENTITY_EXPRESSION ) {
return INVALID_PREDICATE_TYPE;
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ public class Mapping {
@JsonProperty("object_source_version")
private String objectSourceVersion;

@JsonProperty("predicate_type")
private EntityType predicateType;

@JsonProperty("mapping_provider")
@URI
private String mappingProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public class MappingSet {
@Propagatable
private String objectSourceVersion;

@JsonProperty("predicate_type")
@Propagatable
private EntityType predicateType;

@JsonProperty("mapping_provider")
@Propagatable
@URI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class ValidatorTest {

@Test
void testInvalidMappings() throws SSSOMFormatException, IOException {
void testMappingsWithMissingRequiredSlots() throws SSSOMFormatException, IOException {
TSVReader reader = new TSVReader("src/test/resources/sets/test-missing-required-slots.sssom.tsv");
reader.setValidationEnabled(false); // So we can check each mapping ourselves
MappingSet ms = reader.read();
Expand All @@ -41,4 +41,18 @@ void testInvalidMappings() throws SSSOMFormatException, IOException {
Assertions.assertEquals(expectedErrors[i], v.validate(ms.getMappings().get(i)));
}
}

@Test
void testMappingsWithInvalidPredicateTypes() throws SSSOMFormatException, IOException {
TSVReader reader = new TSVReader("src/test/resources/sets/test-predicate-types.sssom.tsv");
reader.setValidationEnabled(false);
MappingSet ms = reader.read();

String[] expectedErrors = { null, null, Validator.INVALID_PREDICATE_TYPE, Validator.INVALID_PREDICATE_TYPE };

Validator v = new Validator();
for ( int i = 0, n = ms.getMappings().size(); i < n; i++ ) {
Assertions.assertEquals(expectedErrors[i], v.validate(ms.getMappings().get(i)));
}
}
}
10 changes: 10 additions & 0 deletions core/src/test/resources/sets/test-predicate-types.sssom.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#curie_map:
# COMENT: https://example.com/entities/
# ORGENT: https://example.org/entities/
#mapping_set_id: https://example.org/sets/test-predicate-types
#license: https://creativecommons.org/licenses/by/4.0/
subject_id subject_label predicate_id object_id object_label mapping_justification predicate_type
ORGENT:0001 alice skos:closeMatch COMENT:0011 alpha semapv:ManualMappingCuration owl object property
ORGENT:0002 bob skos:closeMatch COMENT:0012 beta semapv:ManualMappingCuration owl annotation property
ORGENT:0004 daphne skos:closeMatch COMENT:0014 delta semapv:ManualMappingCuration rdfs literal
ORGENT:0005 eve skos:closeMatch COMENT:0015 epsilon semapv:ManualMappingCuration composed entity expression
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ cardField : 'mapping_cardinality' | 'cardinality';

entField : 'object_type'
| 'subject_type'
| 'predicate_type'
;

idValue : CURIE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.HashSet;
import java.util.Set;

import org.incenp.obofoundry.sssom.model.EntityType;
import org.incenp.obofoundry.sssom.model.Mapping;
import org.incenp.obofoundry.sssom.transform.IMappingTransformer;
import org.semanticweb.owlapi.model.IRI;
Expand Down Expand Up @@ -74,10 +75,31 @@ public DirectAxiomGenerator(OWLOntology ontology) {
public OWLAxiom transform(Mapping mapping) {
OWLAxiom axiom = null;
String predicate = mapping.getPredicateId();
EntityType predicateType = mapping.getPredicateType();
IRI subject = IRI.create(mapping.getSubjectId());
IRI object = IRI.create(mapping.getObjectId());

if ( predicate.equals(OWL_EQUIVALENT_CLASS) ) {
/*
* The type of axiom to generate is dictated by the type of the predicate, which
* we obtain from (by order of precedence):
*
* (1) the mapping itself, if it has a `predicate_type` slot set to either `owl
* annotation property` or `owl object property`;
*
* (2) some built-in knowledge for a handful of predicates (owl:equivalentClass,
* rdfs:subClassOf, and the predicates listed in ANNOTATION_PREDICATES);
*
* (3) the helper ontology, it it declares an annotation or object property with
* a matching IRI.
*/

if ( predicateType == EntityType.OWL_ANNOTATION_PROPERTY ) {
axiom = factory.getOWLAnnotationAssertionAxiom(factory.getOWLAnnotationProperty(IRI.create(predicate)),
subject, object);
} else if ( predicateType == EntityType.OWL_OBJECT_PROPERTY ) {
axiom = factory.getOWLSubClassOfAxiom(factory.getOWLClass(subject), factory.getOWLObjectSomeValuesFrom(
factory.getOWLObjectProperty(IRI.create(predicate)), factory.getOWLClass(object)));
} else if ( predicate.equals(OWL_EQUIVALENT_CLASS) ) {
axiom = factory.getOWLEquivalentClassesAxiom(factory.getOWLClass(object), factory.getOWLClass(object));
} else if ( predicate.equals(RDFS_SUBCLASS_OF) ) {
axiom = factory.getOWLSubClassOfAxiom(factory.getOWLClass(subject), factory.getOWLClass(object));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,10 @@ public IMappingFilter visitEntityTypeFilterItem(SSSOMTransformParser.EntityTypeF
case "subject_type":
filter = (mapping) -> mapping.getSubjectType() == et;
break;

case "predicate_type":
filter = (mapping) -> mapping.getPredicateType() == et;
break;
}

return addFilter(new NamedFilter(String.format("%s==%s", fieldName, value), filter));
Expand Down

0 comments on commit 59b5b78

Please sign in to comment.