Skip to content

Commit

Permalink
Merge pull request #1291 from b2ihealthcare/issue/SO-6101-annotation-…
Browse files Browse the repository at this point in the history
…properties-in-delegateontology

fix(snomed.reasoner): Add support for annotation properties in DelegateOntology as well
  • Loading branch information
cmark authored May 8, 2024
2 parents 297f06a + 0acc688 commit 2d5ed54
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static com.b2international.snowowl.snomed.core.rest.SnomedClassificationRestRequests.*;
import static com.b2international.snowowl.snomed.core.rest.SnomedComponentRestRequests.createComponent;
import static com.b2international.snowowl.snomed.core.rest.SnomedComponentRestRequests.deleteComponent;
import static com.b2international.snowowl.snomed.core.rest.SnomedComponentRestRequests.getComponent;
import static com.b2international.snowowl.snomed.core.rest.SnomedRestFixtures.*;
import static com.b2international.snowowl.test.commons.codesystem.CodeSystemRestRequests.createCodeSystem;
Expand Down Expand Up @@ -588,9 +589,13 @@ public void issue_SO_4985_testExtensionModuleChange() throws Exception {
public void issue_SO_6106_testSubAnnotationPropertyOfAxiomClassification() throws Exception {
String parentConceptId = createNewConcept(branchPath);
String childConceptId = createNewConcept(branchPath, parentConceptId);

SnomedConcept childConcept = getConcept(childConceptId, "relationships()");
childConcept.getRelationships()
.forEach(r -> deleteComponent(branchPath, SnomedComponentType.RELATIONSHIP, r.getId(), false));

createNewRefSetMember(branchPath, childConceptId, Concepts.REFSET_OWL_AXIOM, Map.of(
SnomedRf2Headers.FIELD_OWL_EXPRESSION, "SubAnnotationPropertyOf(: " + childConceptId + " :" + parentConceptId + ")"));
SnomedRf2Headers.FIELD_OWL_EXPRESSION, String.format("SubAnnotationPropertyOf(:%s :%s)", childConceptId, parentConceptId)));

String classificationId = getClassificationJobId(beginClassification(branchPath));
waitForClassificationJob(branchPath, classificationId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,13 +719,14 @@ public ReasonerTaxonomyBuilder addActiveAxioms(final RevisionSearcher searcher)
final StringTokenizer tok = new StringTokenizer(expression.toLowerCase(Locale.ENGLISH), "(): ");
boolean isSubPropertyOf = false;

// OWL axiom types that we are expecting here, four of which requires special handling:
// OWL axiom types that we are expecting here, five of which requires special handling:
//
// [ ] SubClassOf(...)
// [ ] EquivalentClasses(...)
// [+] SubObjectPropertyOf(ObjectPropertyChain(:246093002 :738774007) :246093002)
// [+] SubObjectPropertyOf(:x :y)
// [+] SubDataPropertyOf(:x :y)
// [+] SubAnnotationPropertyOf(:x :y)
// [+] TransitiveObjectProperty(:774081006)
// [ ] ReflexiveObjectProperty(...)
try {
Expand All @@ -750,7 +751,7 @@ public ReasonerTaxonomyBuilder addActiveAxioms(final RevisionSearcher searcher)
isSubPropertyOf = true;
}

// Collect the OWL axiom only if it is not of type "Sub<Object|Data>PropertyOf"
// Collect the OWL axiom only if it is not of type "Sub<Object|Data|Annotation>PropertyOf"
if (!isSubPropertyOf) {
axioms.add(expression);
}
Expand Down Expand Up @@ -787,7 +788,7 @@ public ReasonerTaxonomyBuilder addActiveAxioms(final RevisionSearcher searcher)

if (isSubPropertyOf) {
/*
* XXX: Register "Sub<Object|Data>PropertyOf" axioms as "stated parents", so that we
* XXX: Register "Sub<Object|Data|Annotation>PropertyOf" axioms as "stated parents", so that we
* can create both the original axiom _and_ a SubClassOf axiom for a (punted)
* OWL class representing the property concept.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public final class DelegateOntology extends DelegateOntologyStub implements OWLM
private static final long PRE_2018_OBJECT_ATTRIBUTE = Long.parseLong(Concepts.CONCEPT_MODEL_ATTRIBUTE);
private static final long PRE_2018_DATA_ATTRIBUTE = Long.parseLong(Concepts.SG_CONCRETE_DOMAIN_ATTRIBUTE);

private static final long ANNOTATION_ATTRIBUTE = Long.parseLong(Concepts.ANNOTATION_ATTRIBUTE);

private static final long IS_A = Long.parseLong(Concepts.IS_A);
private static final long ROLE_GROUP = Long.parseLong(Concepts.ROLE_GROUP);

Expand Down Expand Up @@ -237,6 +239,52 @@ private long nextApplicableParentId() {
return -1L;
}
}

private final class SubAnnotationPropertyOfAxiomIterator extends AbstractIterator<OWLSubAnnotationPropertyOfAxiom> {
private final LongIterator childIterator;

private long childId = -1L;
private LongIterator parentIterator;

public SubAnnotationPropertyOfAxiomIterator(final LongIterator childIterator) {
this.childIterator = childIterator;
}

@Override
protected OWLSubAnnotationPropertyOfAxiom computeNext() {
final long parentId = nextApplicableParentId();
if (parentId == -1L) {
return endOfData();
}

final OWLAnnotationProperty childProperty = getConceptAnnotationProperty(childId);
final OWLAnnotationProperty parentProperty = getConceptAnnotationProperty(parentId);
return getOWLSubAnnotationPropertyOfAxiom(childProperty, parentProperty);
}

private long nextApplicableParentId() {
// Check if there are more parents to return for the current value of "childId"
if (parentIterator != null) {
while (parentIterator.hasNext()) {
return parentIterator.next();
}
}

// Otherwise, look for the next child which has parents
while (childIterator.hasNext()) {
childId = childIterator.next();
parentIterator = taxonomy.getStatedAncestors()
.getDestinations(childId, true)
.iterator();

while (parentIterator.hasNext()) {
return parentIterator.next();
}
}

return -1L;
}
}

private final class SubClassOfAxiomIterator extends AbstractIterator<OWLSubClassOfAxiom> {
private final LongIterator childIterator;
Expand Down Expand Up @@ -376,6 +424,7 @@ private static DefaultPrefixManager createPrefixManager() {

private final long objectAttributeId;
private final long dataAttributeId;
private final long annotationAttributeId;
private final LongSet neverGroupedIds;

public DelegateOntology(final OWLOntologyManager manager,
Expand All @@ -400,6 +449,12 @@ public DelegateOntology(final OWLOntologyManager manager,
dataAttributeId = PRE_2018_DATA_ATTRIBUTE;
}

if (taxonomy.getConceptMap().getInternalId(ANNOTATION_ATTRIBUTE) != -1) {
annotationAttributeId = ANNOTATION_ATTRIBUTE;
} else {
annotationAttributeId = -1L;
}

if (!taxonomy.getNeverGroupedTypeIds().isEmpty()) {
this.neverGroupedIds = taxonomy.getNeverGroupedTypeIds();
} else {
Expand Down Expand Up @@ -539,6 +594,7 @@ public Iterator<OWLLogicalAxiom> iterator() {
objectAttributeSubClassOfAxioms(),
dataAttributeSubPropertyOfAxioms(),
dataAttributeSubClassOfAxioms(),
annotationAttributeSubClassOfAxioms(),
disjointUnionAxioms());
}

Expand All @@ -554,7 +610,10 @@ public Set<OWLAxiom> getAxioms() {
return new AbstractSet<OWLAxiom>() {
@Override
public Iterator<OWLAxiom> iterator() {
return Iterators.concat(conceptFsnAxioms(), getLogicalAxioms().iterator());
return Iterators.concat(
conceptFsnAxioms(),
annotationAttributeSubPropertyOfAxioms(),
getLogicalAxioms().iterator());
}

@Override
Expand All @@ -572,12 +631,14 @@ public int getLogicalAxiomCount() {
+ objectHierarchyCount() // objectAttributeSubClassOfAxioms()
+ dataHierarchyCount() // dataAttributeSubPropertyOfAxioms()
+ dataHierarchyCount() // dataAttributeSubClassOfAxioms()
+ annotationHierarchyCount() // annotationAttributeSubClassOfAxioms()
+ disjointUnionCount(); // disjointUnionAxioms()
}

@Override
public int getAxiomCount() {
return conceptFsnAxiomCount() // conceptFsnAxioms()
+ annotationHierarchyCount() // annotationAttributeSubPropertyOfAxioms()
+ getLogicalAxiomCount();
}

Expand Down Expand Up @@ -679,6 +740,18 @@ private int dataHierarchyCount() {
return hierarchyCount(dataAttributeId);
}

private Iterator<OWLSubAnnotationPropertyOfAxiom> annotationAttributeSubPropertyOfAxioms() {
return new SubAnnotationPropertyOfAxiomIterator(annotationAttributeIdIterator());
}

private Iterator<OWLSubClassOfAxiom> annotationAttributeSubClassOfAxioms() {
return new SubClassOfAxiomIterator(annotationAttributeIdIterator());
}

private int annotationHierarchyCount() {
return hierarchyCount(annotationAttributeId);
}

private int hierarchyCount(final long ancestorId) {
return getAllSubTypes(ancestorId).size();
}
Expand Down Expand Up @@ -726,6 +799,10 @@ private LongIterator objectAttributeIdIterator() {
private LongIterator dataAttributeIdIterator() {
return getAllSubTypes(dataAttributeId).iterator();
}

private LongIterator annotationAttributeIdIterator() {
return getAllSubTypes(annotationAttributeId).iterator();
}

private LongIterator exhaustiveIdIterator() {
return taxonomy.getExhaustiveConcepts().iterator();
Expand Down Expand Up @@ -786,6 +863,10 @@ private OWLObjectProperty getConceptObjectProperty(final long conceptId) {
private OWLDataProperty getConceptDataProperty(final long conceptId) {
return getOWLDataProperty(PREFIX_SCT + conceptId);
}

private OWLAnnotationProperty getConceptAnnotationProperty(final long conceptId) {
return getOWLAnnotationProperty(PREFIX_SCT + conceptId);
}

private OWLClassExpression getRelationshipExpression(final StatementFragment fragment) {
return fragment.map(
Expand Down Expand Up @@ -989,6 +1070,10 @@ private OWLDataProperty getOWLDataProperty(final String abbreviatedIRI) {
return getDataFactory().getOWLDataProperty(abbreviatedIRI, prefixManager);
}

private OWLAnnotationProperty getOWLAnnotationProperty(final String abbreviatedIRI) {
return getDataFactory().getOWLAnnotationProperty(abbreviatedIRI, prefixManager);
}

private OWLClassExpression getOWLObjectIntersectionOf(final Set<OWLClassExpression> conjuncts) {
if (conjuncts.size() > 1) {
return getDataFactory().getOWLObjectIntersectionOf(conjuncts);
Expand Down Expand Up @@ -1059,4 +1144,8 @@ private OWLSubObjectPropertyOfAxiom getOWLSubObjectPropertyOfAxiom(final OWLObje
private OWLSubDataPropertyOfAxiom getOWLSubDataPropertyOfAxiom(final OWLDataPropertyExpression child, final OWLDataPropertyExpression parent) {
return getDataFactory().getOWLSubDataPropertyOfAxiom(child, parent);
}

private OWLSubAnnotationPropertyOfAxiom getOWLSubAnnotationPropertyOfAxiom(final OWLAnnotationProperty child, final OWLAnnotationProperty parent) {
return getDataFactory().getOWLSubAnnotationPropertyOfAxiom(child, parent);
}
}

0 comments on commit 2d5ed54

Please sign in to comment.