diff --git a/core/src/main/java/org/incenp/obofoundry/kgcl/DirectOWLTranslator.java b/core/src/main/java/org/incenp/obofoundry/kgcl/DirectOWLTranslator.java index e180c5c..95882f9 100644 --- a/core/src/main/java/org/incenp/obofoundry/kgcl/DirectOWLTranslator.java +++ b/core/src/main/java/org/incenp/obofoundry/kgcl/DirectOWLTranslator.java @@ -66,7 +66,6 @@ import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom; import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom; import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom; -import org.semanticweb.owlapi.model.OWLObjectProperty; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLOntologyChange; import org.semanticweb.owlapi.model.OWLSubClassOfAxiom; @@ -146,47 +145,6 @@ private IRI findClass(Change v, String id) { return classIRI; } - private Set findEdges(IRI subjectIRI, IRI objectIRI, IRI predicateIRI) { - HashSet axioms = new HashSet(); - OWLClass object = factory.getOWLClass(objectIRI); - OWLObjectProperty property = null; - if ( predicateIRI != null && !OWLRDFVocabulary.RDFS_SUBCLASS_OF.getIRI().equals(predicateIRI) ) { - property = factory.getOWLObjectProperty(predicateIRI); - } - - for ( OWLAxiom axiom : ontology.getAxioms(factory.getOWLClass(subjectIRI), Imports.INCLUDED) ) { - if ( axiom instanceof OWLSubClassOfAxiom ) { - OWLSubClassOfAxiom scoa = (OWLSubClassOfAxiom) axiom; - OWLClassExpression objectExpression = scoa.getSuperClass(); - if ( objectExpression.containsEntityInSignature(object) ) { - if ( predicateIRI == null ) { - // No predicate specified, so any edge between subject and object is a match - axioms.add(scoa); - } else if ( property != null - && objectExpression.getObjectPropertiesInSignature().contains(property) ) { - // Predicate is a property and this expression has it, so it's a match - axioms.add(scoa); - } else if ( property == null && objectExpression.isNamed() ) { - // Predicate is rdfs:subClassOf and this expression is the object, it's a match - axioms.add(scoa); - } - } - } - } - - // Search for annotations that can be assimilated to edges (annotations whose - // value is an IRI) - for ( OWLAnnotationAssertionAxiom axiom : ontology.getAnnotationAssertionAxioms(subjectIRI) ) { - if ( axiom.getValue().isIRI() && axiom.getValue().asIRI().get().equals(objectIRI) ) { - if ( predicateIRI == null || axiom.getProperty().getIRI().equals(predicateIRI) ) { - axioms.add(axiom); - } - } - } - - return axioms; - } - private EdgeType getEdgeType(IRI predicateIRI) { if ( predicateIRI.equals(OWLRDFVocabulary.RDFS_SUBCLASS_OF.getIRI()) ) { return EdgeType.SUBCLASS; @@ -1019,10 +977,4 @@ public OWLAxiom visit(OWLDisjointUnionAxiom axiom) { axiom.getAnnotations()); } } - - private enum EdgeType { - SUBCLASS, - RESTRICTION, - ANNOTATION - } } diff --git a/core/src/main/java/org/incenp/obofoundry/kgcl/EdgeType.java b/core/src/main/java/org/incenp/obofoundry/kgcl/EdgeType.java new file mode 100644 index 0000000..94ccfce --- /dev/null +++ b/core/src/main/java/org/incenp/obofoundry/kgcl/EdgeType.java @@ -0,0 +1,33 @@ +/* + * KGCL-Java - KGCL library for Java + * Copyright © 2024 Damien Goutte-Gattat + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the Gnu General Public License + * along with this program. If not, see . + */ + +package org.incenp.obofoundry.kgcl; + +/** + * Represents the type of an edge between two nodes. + */ +public enum EdgeType { + /** A rdfs:subClassOf edge between two classes. */ + SUBCLASS, + + /** An edge representing an existential restriction between two classes. */ + RESTRICTION, + + /** An edge that is an annotation between a class and an IRI. */ + ANNOTATION +} diff --git a/core/src/main/java/org/incenp/obofoundry/kgcl/OWLTranslator.java b/core/src/main/java/org/incenp/obofoundry/kgcl/OWLTranslator.java index 9342f5d..9cfbadd 100644 --- a/core/src/main/java/org/incenp/obofoundry/kgcl/OWLTranslator.java +++ b/core/src/main/java/org/incenp/obofoundry/kgcl/OWLTranslator.java @@ -28,11 +28,18 @@ import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom; import org.semanticweb.owlapi.model.OWLAnnotationValue; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLClassExpression; import org.semanticweb.owlapi.model.OWLDataFactory; import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLObjectProperty; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLOntologyChange; +import org.semanticweb.owlapi.model.OWLSubClassOfAxiom; +import org.semanticweb.owlapi.model.parameters.Imports; import org.semanticweb.owlapi.reasoner.OWLReasoner; +import org.semanticweb.owlapi.vocab.OWLRDFVocabulary; /** * Base class to translate KGCL change objects into OWL axioms. @@ -216,4 +223,60 @@ protected OWLLiteral getLiteral(NodeChange change, String oldLang) { protected OWLLiteral getLiteral(NodeChange change) { return getLiteral(change, null); } + + /** + * Gets all axioms representing edges between a subject and an object. + * + * @param subject The subject to look for. + * @param object The object to look for. + * @param predicate The predicate to look for. May be {@code null}, in which + * case the method will return all edges between the subject + * and the object regardless of their predicate. + * @return A set of matching axioms. + */ + protected Set findEdges(IRI subject, IRI object, IRI predicate) { + HashSet edges = new HashSet(); + + OWLObjectProperty property = null; + if ( predicate != null && !OWLRDFVocabulary.RDFS_SUBCLASS_OF.getIRI().equals(predicate) ) { + property = factory.getOWLObjectProperty(predicate); + } + + // Search for edges between classes + for ( OWLAxiom axiom : ontology.getAxioms(factory.getOWLClass(subject), Imports.INCLUDED) ) { + if ( axiom instanceof OWLSubClassOfAxiom ) { + OWLSubClassOfAxiom scoa = (OWLSubClassOfAxiom) axiom; + OWLClassExpression objectExpression = scoa.getSuperClass(); + OWLClass objectClass = factory.getOWLClass(object); + + if ( objectExpression.containsEntityInSignature(objectClass) && objectExpression.getClassesInSignature().size() == 1 ) { + if ( predicate == null ) { + // No predicate specified, so any edge between subject and object is a match + edges.add(scoa); + } else if ( property != null + && objectExpression.getObjectPropertiesInSignature().contains(property) ) { + // Predicate is a property and this expression has it, so it's a match + edges.add(scoa); + } else if ( property == null && objectExpression.isNamed() ) { + // Predicate is rdfs:subClassOf and this expression is the object, it's a match + edges.add(scoa); + } + } + } + } + + // TODO: Search for edges between properties or individuals + + // Search for annotations that can be assimilated to edges (annotations whose + // value is an IRI) + for ( OWLAnnotationAssertionAxiom axiom : ontology.getAnnotationAssertionAxioms(subject) ) { + if ( axiom.getValue().isIRI() && axiom.getValue().asIRI().get().equals(object) ) { + if ( predicate == null || axiom.getProperty().getIRI().equals(predicate) ) { + edges.add(axiom); + } + } + } + + return edges; + } }