org.obolibrary.macro.AbstractMacroExpansionVisitor Maven / Gradle / Ivy
package org.obolibrary.macro;
import static org.obolibrary.obo2owl.Obo2OWLConstants.Obo2OWLVocabulary.IRI_IAO_0000424;
import static org.obolibrary.obo2owl.Obo2OWLConstants.Obo2OWLVocabulary.IRI_IAO_0000425;
import static org.semanticweb.owlapi.search.EntitySearcher.getAnnotationObjects;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.asSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import org.obolibrary.obo2owl.Obo2OWLConstants;
import org.semanticweb.owlapi.manchestersyntax.renderer.ParserException;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLAnnotationValue;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLAxiomVisitorEx;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
import org.semanticweb.owlapi.model.OWLDataExactCardinality;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataHasValue;
import org.semanticweb.owlapi.model.OWLDataMaxCardinality;
import org.semanticweb.owlapi.model.OWLDataMinCardinality;
import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLDataVisitorEx;
import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNamedObject;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectOneOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Empty abstract visitor for macro expansion. This class allows to minimize the code in the actual
* visitors, as they only need to overwrite the relevant methods.
*/
public abstract class AbstractMacroExpansionVisitor implements OWLAxiomVisitorEx {
static final Logger LOG = LoggerFactory.getLogger(AbstractMacroExpansionVisitor.class);
static final Set EMPTY_ANNOTATIONS = Collections.emptySet();
protected final Map expandExpressionMap;
protected final OWLAnnotationProperty OIO_ISEXPANSION;
protected final OWLAnnotation expansionMarkerAnnotation;
final OWLDataFactory df;
final Map expandAssertionToMap;
protected OWLDataVisitorEx rangeVisitor;
protected OWLClassExpressionVisitorEx classVisitor;
protected ManchesterSyntaxTool manchesterSyntaxTool;
private boolean shouldAddExpansionMarker = false;
protected AbstractMacroExpansionVisitor(OWLOntology ontology,
boolean shouldAddExpansionMarker) {
this(ontology);
this.shouldAddExpansionMarker = shouldAddExpansionMarker;
}
protected AbstractMacroExpansionVisitor(OWLOntology o) {
df = o.getOWLOntologyManager().getOWLDataFactory();
expandExpressionMap = new HashMap<>();
expandAssertionToMap = new HashMap<>();
OWLAnnotationProperty ap424 = df.getOWLAnnotationProperty(IRI_IAO_0000424.getIRI());
o.objectPropertiesInSignature()
.forEach(p -> getAnnotationObjects(p, o.importsClosure(), ap424)
.forEach(a -> mapToExpand(p, a)));
o.annotationPropertiesInSignature().forEach(p -> expandAssertions(o, p));
OIO_ISEXPANSION = df.getOWLAnnotationProperty(
IRI.create(Obo2OWLConstants.OIOVOCAB_IRI_PREFIX, "is_expansion"));
expansionMarkerAnnotation = df.getOWLAnnotation(OIO_ISEXPANSION, df.getOWLLiteral(true));
}
protected void mapToExpand(OWLObjectProperty p, OWLAnnotation a) {
OWLAnnotationValue v = a.getValue();
if (v instanceof OWLLiteral) {
String str = ((OWLLiteral) v).getLiteral();
LOG.info("mapping {} to {}", p.getIRI(), str);
expandExpressionMap.put(p.getIRI(), str);
}
}
/**
* @return value for expansion annotation
*/
public OWLAnnotation getExpansionMarkerAnnotation() {
return expansionMarkerAnnotation;
}
@Override
public OWLAxiom doDefault(Object o) {
return (OWLAxiom) o;
}
/**
* @return value for OIO is_expansion
*/
public OWLAnnotationProperty getOIO_ISEXPANSION() {
return OIO_ISEXPANSION;
}
/**
* @param input ontology
*/
public void rebuild(OWLOntology input) {
manchesterSyntaxTool = new ManchesterSyntaxTool(input);
}
/**
* @return Manchester syntax tool
*/
public ManchesterSyntaxTool getTool() {
return manchesterSyntaxTool;
}
protected void expandAssertions(OWLOntology o, OWLAnnotationProperty p) {
OWLAnnotationProperty ap425 = df.getOWLAnnotationProperty(IRI_IAO_0000425.getIRI());
getAnnotationObjects(p, o.importsClosure(), ap425).map(a -> a.getValue().asLiteral())
.filter(v -> v.isPresent()).forEach(v -> {
String str = v.get().getLiteral();
LOG.info("assertion mapping {} to {}", p, str);
expandAssertionToMap.put(p.getIRI(), str);
});
}
@Nullable
protected OWLClassExpression expandObject(Object filler, OWLObjectPropertyExpression p) {
OWLClassExpression result = null;
IRI iri = ((OWLObjectProperty) p).getIRI();
IRI templateVal = null;
if (expandExpressionMap.containsKey(iri)) {
if (filler instanceof OWLObjectOneOf) {
templateVal = valFromOneOf(filler);
}
if (filler instanceof OWLNamedObject) {
templateVal = ((OWLNamedObject) filler).getIRI();
}
if (templateVal != null) {
result = resultFromVal(iri, templateVal);
}
}
return result;
}
@Nullable
protected OWLClassExpression resultFromVal(IRI iri, IRI templateVal) {
String tStr = expandExpressionMap.get(iri);
String exStr = tStr.replace("?Y", manchesterSyntaxTool.getId(templateVal));
try {
return manchesterSyntaxTool.parseManchesterExpression(exStr);
} catch (ParserException e) {
LOG.error(e.getMessage(), e);
return null;
}
}
@Nullable
protected IRI valFromOneOf(Object filler) {
Iterator extends OWLIndividual> inds = ((OWLObjectOneOf) filler).individuals()
.filter(x -> x instanceof OWLNamedIndividual).iterator();
if (inds.hasNext()) {
OWLIndividual ind = inds.next();
// more than one value? Then cannot select a value
if (!inds.hasNext()) {
return ((OWLNamedObject) ind).getIRI();
}
}
return null;
}
// Conversion of non-class expressions to MacroExpansionVisitor
@Override
public OWLAxiom visit(OWLSubClassOfAxiom axiom) {
OWLClassExpression subClass = axiom.getSubClass();
OWLClassExpression newSubclass = subClass.accept(classVisitor);
OWLClassExpression superClass = axiom.getSuperClass();
OWLClassExpression newSuperclass = superClass.accept(classVisitor);
if (subClass.equals(newSubclass) && superClass.equals(newSuperclass)) {
return axiom;
} else {
return df.getOWLSubClassOfAxiom(newSubclass, newSuperclass,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
}
/**
* @param axiom annotation source
* @return new set of annotations
*/
public Set getAnnotationsWithOptionalExpansionMarker(OWLAxiom axiom) {
Set annotations = asSet(axiom.annotations());
if (shouldAddExpansionMarker) {
annotations.add(expansionMarkerAnnotation);
}
return annotations;
}
@Override
public OWLAxiom visit(OWLDisjointClassesAxiom axiom) {
Set ops = new HashSet<>();
AtomicBoolean sawChange = new AtomicBoolean(false);
axiom.classExpressions().forEach(op -> {
OWLClassExpression newOp = op.accept(classVisitor);
ops.add(newOp);
if (!op.equals(newOp)) {
sawChange.set(true);
}
});
if (!sawChange.get()) {
return axiom;
}
return df.getOWLDisjointClassesAxiom(ops, getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLDisjointUnionAxiom axiom) {
Set newOps = new HashSet<>();
AtomicBoolean sawChange = new AtomicBoolean(false);
axiom.classExpressions().forEach(op -> {
OWLClassExpression newOp = op.accept(classVisitor);
newOps.add(newOp);
if (!op.equals(newOp)) {
sawChange.set(true);
}
});
if (!sawChange.get()) {
return axiom;
}
return df.getOWLDisjointUnionAxiom(axiom.getOWLClass(), newOps,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLDataPropertyDomainAxiom axiom) {
OWLClassExpression domain = axiom.getDomain();
OWLClassExpression newDomain = domain.accept(classVisitor);
if (domain.equals(newDomain)) {
return axiom;
}
return df.getOWLDataPropertyDomainAxiom(axiom.getProperty(), newDomain,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLObjectPropertyDomainAxiom axiom) {
OWLClassExpression domain = axiom.getDomain();
OWLClassExpression newDomain = domain.accept(classVisitor);
if (domain.equals(newDomain)) {
return axiom;
}
return df.getOWLObjectPropertyDomainAxiom(axiom.getProperty(), newDomain,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLObjectPropertyRangeAxiom axiom) {
OWLClassExpression range = axiom.getRange();
OWLClassExpression newRange = range.accept(classVisitor);
if (range.equals(newRange)) {
return axiom;
}
return df.getOWLObjectPropertyRangeAxiom(axiom.getProperty(), newRange,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLDataPropertyRangeAxiom axiom) {
OWLDataRange range = axiom.getRange();
OWLDataRange newRange = range.accept(rangeVisitor);
if (range.equals(newRange)) {
return axiom;
}
return df.getOWLDataPropertyRangeAxiom(axiom.getProperty(), newRange,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
@Override
public OWLAxiom visit(OWLClassAssertionAxiom axiom) {
OWLClassExpression classExpression = axiom.getClassExpression();
if (classExpression.isAnonymous()) {
OWLClassExpression newClassExpression = classExpression.accept(classVisitor);
if (!classExpression.equals(newClassExpression)) {
return df.getOWLClassAssertionAxiom(newClassExpression, axiom.getIndividual(),
getAnnotationsWithOptionalExpansionMarker(axiom));
}
}
return axiom;
}
@Override
public OWLAxiom visit(OWLEquivalentClassesAxiom axiom) {
Set newExpressions = new HashSet<>();
AtomicBoolean sawChange = new AtomicBoolean(false);
axiom.classExpressions().forEach(op -> {
OWLClassExpression newExpression = op.accept(classVisitor);
newExpressions.add(newExpression);
if (!op.equals(newExpression)) {
sawChange.set(true);
}
});
if (!sawChange.get()) {
return axiom;
}
return df.getOWLEquivalentClassesAxiom(newExpressions,
getAnnotationsWithOptionalExpansionMarker(axiom));
}
/**
* class expression visitor
*/
public abstract class AbstractClassExpressionVisitorEx
implements OWLClassExpressionVisitorEx {
protected AbstractClassExpressionVisitorEx() {}
@Override
public OWLClassExpression visit(OWLObjectIntersectionOf ce) {
return df.getOWLObjectIntersectionOf(ce.operands().map(o -> o.accept(this)));
}
@Override
public OWLClassExpression visit(OWLObjectUnionOf ce) {
return df.getOWLObjectUnionOf(ce.operands().map(o -> o.accept(this)));
}
@Override
public OWLClassExpression visit(OWLObjectComplementOf ce) {
return df.getOWLObjectComplementOf(ce.getOperand().accept(this));
}
@Override
public OWLClassExpression visit(OWLObjectSomeValuesFrom ce) {
OWLClassExpression filler = ce.getFiller();
OWLObjectPropertyExpression p = ce.getProperty();
OWLClassExpression result = null;
if (p.isOWLObjectProperty()) {
result = expandOWLObjSomeVal(filler, p);
}
if (result == null) {
result = df.getOWLObjectSomeValuesFrom(ce.getProperty(), filler.accept(this));
}
return result;
}
@Nullable
protected abstract OWLClassExpression expandOWLObjSomeVal(OWLClassExpression filler,
OWLObjectPropertyExpression p);
@Override
public OWLClassExpression visit(OWLObjectHasValue ce) {
OWLClassExpression result = null;
OWLIndividual filler = ce.getFiller();
OWLObjectPropertyExpression p = ce.getProperty();
if (p.isOWLObjectProperty()) {
result = expandOWLObjHasVal(ce, filler, p);
}
if (result == null) {
result = df.getOWLObjectHasValue(ce.getProperty(), filler);
}
return result;
}
@Nullable
protected abstract OWLClassExpression expandOWLObjHasVal(OWLObjectHasValue desc,
OWLIndividual filler, OWLObjectPropertyExpression p);
@Override
public OWLClassExpression visit(OWLObjectAllValuesFrom ce) {
return ce.getFiller().accept(this);
}
@Override
public OWLClassExpression visit(OWLObjectMinCardinality ce) {
OWLClassExpression filler = ce.getFiller().accept(this);
return df.getOWLObjectMinCardinality(ce.getCardinality(), ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLObjectExactCardinality ce) {
return ce.asIntersectionOfMinMax().accept(this);
}
@Override
public OWLClassExpression visit(OWLObjectMaxCardinality ce) {
OWLClassExpression filler = ce.getFiller().accept(this);
return df.getOWLObjectMaxCardinality(ce.getCardinality(), ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLDataSomeValuesFrom ce) {
OWLDataRange filler = ce.getFiller().accept(rangeVisitor);
return df.getOWLDataSomeValuesFrom(ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLDataAllValuesFrom ce) {
OWLDataRange filler = ce.getFiller().accept(rangeVisitor);
return df.getOWLDataAllValuesFrom(ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLDataHasValue ce) {
return ce.asSomeValuesFrom().accept(this);
}
@Override
public OWLClassExpression visit(OWLDataExactCardinality ce) {
return ce.asIntersectionOfMinMax().accept(this);
}
@Override
public OWLClassExpression visit(OWLDataMaxCardinality ce) {
int card = ce.getCardinality();
OWLDataRange filler = ce.getFiller().accept(rangeVisitor);
return df.getOWLDataMaxCardinality(card, ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLDataMinCardinality ce) {
int card = ce.getCardinality();
OWLDataRange filler = ce.getFiller().accept(rangeVisitor);
return df.getOWLDataMinCardinality(card, ce.getProperty(), filler);
}
@Override
public OWLClassExpression visit(OWLClass ce) {
return ce;
}
@Override
public OWLClassExpression visit(OWLObjectHasSelf ce) {
return ce;
}
@Override
public OWLClassExpression visit(OWLObjectOneOf ce) {
return ce;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy