All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.obolibrary.macro.MacroExpansionVisitor Maven / Gradle / Ivy

Go to download

A java library for converting obo format documents to OWL, and for converting (a subset of) OWL to obo format. This version has been slightly modified to be included directly in the OWL API. The upstream code for this module and its authors can be found at https://code.google.com/p/oboformat/.

The newest version!
package org.obolibrary.macro;

import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.add;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.asList;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.annotation.Nullable;

import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
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.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author cjm TODO - allow use of prefixes
 */
public class MacroExpansionVisitor {

    protected static final Logger LOG = LoggerFactory.getLogger(MacroExpansionVisitor.class);
    protected final OWLOntology inputOntology;
    protected final OWLOntologyManager manager;
    protected final Visitor visitor;
    protected final AbstractDataVisitorEx dataVisitor;
    protected final boolean shouldAddExpansionMarker;
    protected boolean shouldTransferAnnotations = false;
    protected Set extraAnnotations;

    /**
     * @param ontology ontology to use
     */
    public MacroExpansionVisitor(OWLOntology ontology) {
        this(ontology, AbstractMacroExpansionVisitor.EMPTY_ANNOTATIONS, false, false);
    }

    /**
     * @param ontology                 ontology to use
     * @param shouldAddExpansionMarker true if expansions should be added
     */
    public MacroExpansionVisitor(OWLOntology ontology, boolean shouldAddExpansionMarker) {
        this(ontology, AbstractMacroExpansionVisitor.EMPTY_ANNOTATIONS, false,
            shouldAddExpansionMarker);
    }

    /**
     * @param ontology                  ontology to use
     * @param shouldTransferAnnotations true if annotations should be transferred
     * @param shouldAddExpansionMarker  true if expansions should be added
     */
    public MacroExpansionVisitor(OWLOntology ontology, boolean shouldTransferAnnotations,
        boolean shouldAddExpansionMarker) {
        this(ontology, AbstractMacroExpansionVisitor.EMPTY_ANNOTATIONS, shouldTransferAnnotations,
            shouldAddExpansionMarker);
    }

    /**
     * @param inputOntology             input ontology
     * @param extraAnnotations          extra annotations to add
     * @param shouldTransferAnnotations true if annotations should be transferred
     * @param shouldAddExpansionMarker  true if expansions should be added
     */
    public MacroExpansionVisitor(OWLOntology inputOntology, Set extraAnnotations,
        boolean shouldTransferAnnotations, boolean shouldAddExpansionMarker) {
        this.inputOntology = inputOntology;
        this.extraAnnotations = extraAnnotations;
        this.shouldTransferAnnotations = shouldTransferAnnotations;
        this.shouldAddExpansionMarker = shouldAddExpansionMarker;
        visitor = new Visitor(inputOntology, shouldAddExpansionMarker);
        visitor.rebuild(inputOntology);
        manager = inputOntology.getOWLOntologyManager();
        dataVisitor = new AbstractDataVisitorEx(manager.getOWLDataFactory());
    }

    /**
     * @return new MacroExpansions
     */
    public MacroExpansions getMacroExpansions() {
        return new MacroExpansions();
    }

    /**
     * @return ontology with expanded macros
     */
    public OWLOntology expandAll() {
        MacroExpansions macroExpansions = new MacroExpansions();
        Set newAxioms = macroExpansions.getNewAxioms();
        Set rmAxioms = macroExpansions.getRmAxioms();
        inputOntology.add(newAxioms);
        inputOntology.remove(rmAxioms);
        return inputOntology;
    }

    /**
     * @return true if annotations should be transferred
     */
    public boolean shouldTransferAnnotations() {
        return shouldTransferAnnotations;
    }

    /**
     * @param shouldTransferAnnotations new value
     */
    public void setShouldTransferAnnotations(boolean shouldTransferAnnotations) {
        this.shouldTransferAnnotations = shouldTransferAnnotations;
    }

    /**
     * Call this method to clear internal references.
     */
    public void dispose() {
        visitor.getTool().dispose();
    }

    private class MacroExpansions {

        private final Set newAxioms = new HashSet<>();
        private final Set rmAxioms = new HashSet<>();

        public MacroExpansions() {
            inputOntology.axioms(AxiomType.SUBCLASS_OF).forEach(axiom -> {
                OWLAxiom newAxiom = axiom.accept(visitor);
                replaceIfDifferent(axiom, newAxiom);
            });
            inputOntology.axioms(AxiomType.EQUIVALENT_CLASSES).forEach(axiom -> {
                OWLAxiom newAxiom = axiom.accept(visitor);
                replaceIfDifferent(axiom, newAxiom);
            });
            inputOntology.axioms(AxiomType.CLASS_ASSERTION).forEach(axiom -> {
                OWLAxiom newAxiom = axiom.accept(visitor);
                replaceIfDifferent(axiom, newAxiom);
            });
            add(rmAxioms,
                inputOntology.axioms(AxiomType.ANNOTATION_ASSERTION).filter(this::expand));
        }

        private void replaceIfDifferent(OWLAxiom ax, OWLAxiom exAx) {
            if (!ax.equals(exAx)) {
                newAxioms.add(exAx);
                rmAxioms.add(ax);
            }
        }

        public Set getNewAxioms() {
            return newAxioms;
        }

        public Set getRmAxioms() {
            return rmAxioms;
        }

        private boolean expand(OWLAnnotationAssertionAxiom axiom) {
            OWLAnnotationProperty prop = axiom.getProperty();
            String expandTo = visitor.expandAssertionToMap.get(prop.getIRI());
            HashSet declarations = new HashSet<>();
            AtomicBoolean expandedSomething = new AtomicBoolean(false);
            try {
                if (expandTo != null) {
                    Set annotations = new HashSet<>(extraAnnotations);
                    if (shouldAddExpansionMarker) {
                        annotations.add(visitor.getExpansionMarkerAnnotation());
                    }
                    if (shouldTransferAnnotations()) {
                        add(annotations, axiom.annotations());
                    }
                    // when expanding assertions, the axiom is an annotation
                    // assertion, and the value may be not be explicitly
                    // declared. If it is
                    // not, we assume it is a class
                    IRI axValIRI = (IRI) axiom.getValue();
                    OWLDataFactory dataFactory = visitor.df;
                    OWLClass axValClass = dataFactory.getOWLClass(axValIRI);
                    if (asList(inputOntology.declarationAxioms(axValClass)).isEmpty()) {
                        OWLDeclarationAxiom declarationAxiom =
                            dataFactory.getOWLDeclarationAxiom(axValClass, annotations);
                        declarations.add(declarationAxiom);
                        newAxioms.add(declarationAxiom);
                        manager.addAxiom(inputOntology, declarationAxiom);
                        // we need to sync the MST entity checker with the new
                        // ontology plus declarations;
                        // we do this by creating a new MST - this is not
                        // particularly efficient, a better
                        // way might be to first scan the ontology for all
                        // annotation axioms that will be expanded,
                        // then add the declarations at this point
                        visitor.rebuild(inputOntology);
                    }
                    LOG.info("Template to Expand {}", expandTo);
                    expandTo = expandTo.replaceAll("\\?X",
                        visitor.getTool().getId((IRI) axiom.getSubject()));
                    expandTo = expandTo.replaceAll("\\?Y", visitor.getTool().getId(axValIRI));
                    LOG.info("Expanding {}", expandTo);
                    try {
                        expandAndAddAnnotations(expandTo, expandedSomething, annotations);
                    } catch (Exception ex) {
                        LOG.error(ex.getMessage(), ex);
                    }
                    // TODO:
                }
            } finally {
                inputOntology.remove(declarations);
            }
            return expandedSomething.get();
        }

        protected void expandAndAddAnnotations(String expandTo, AtomicBoolean expandedSomething,
            Set annotations) {
            visitor.getTool().parseManchesterExpressionFrames(expandTo).stream()
                .map(axp -> axp.getAxiom())
                .map(ax -> shouldTransferAnnotations() ? ax.getAnnotatedAxiom(annotations) : ax)
                .forEach(expandedAxiom -> {
                    newAxioms.add(expandedAxiom);
                    expandedSomething.set(true);
                });
        }
    }

    private class Visitor extends AbstractMacroExpansionVisitor {

        Visitor(OWLOntology inputOntology, boolean shouldAddExpansionMarker) {
            super(inputOntology, shouldAddExpansionMarker);
            rangeVisitor = dataVisitor;
            classVisitor = new AbstractMacroExpansionVisitor.AbstractClassExpressionVisitorEx() {

                @Override
                @Nullable
                protected OWLClassExpression expandOWLObjSomeVal(OWLClassExpression filler,
                    OWLObjectPropertyExpression p) {
                    return expandObject(filler, p);
                }

                @Override
                @Nullable
                protected OWLClassExpression expandOWLObjHasVal(OWLObjectHasValue desc,
                    OWLIndividual filler, OWLObjectPropertyExpression p) {
                    OWLClassExpression result = expandObject(filler, p);
                    if (result != null) {
                        result = df.getOWLObjectSomeValuesFrom(desc.getProperty(), result);
                    }
                    return result;
                }
            };
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy