uk.co.flax.biosolr.ontology.core.owl.OWLOntologyHelper.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.flax.biosolr.ontology.core.owl.OWLOntologyHelper.java

Source

/**
 * Copyright (c) 2015 Lemur Consulting Ltd.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package uk.co.flax.biosolr.ontology.core.owl;

import org.apache.commons.lang3.StringUtils;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.co.flax.biosolr.ontology.core.AbstractOntologyHelper;
import uk.co.flax.biosolr.ontology.core.OntologyHelperConfiguration;
import uk.co.flax.biosolr.ontology.core.OntologyHelperException;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * OWL-specific implementation of OntologyHelper.
 *
 * <p>Created by Matt Pearce on 20/10/15.</p>
 * @author Matt Pearce
 */
public class OWLOntologyHelper extends AbstractOntologyHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(OWLOntologyHelper.class);

    private final OWLOntologyConfiguration config;
    private final OWLDataManager dataManager;

    private final Map<IRI, Collection<String>> labels = new HashMap<>();
    private final Map<IRI, Collection<String>> synonyms = new HashMap<>();
    private final Map<IRI, Collection<String>> definitions = new HashMap<>();

    private long lastCallTime;

    /**
     * Construct a new ontology helper instance with a string representing the
     * ontology URI.
     *
     * @param config the ontology configuration, containing the property URIs
     * for labels, synonyms, etc.
     * @throws URISyntaxException if the URI cannot be parsed.
     */
    public OWLOntologyHelper(OWLOntologyConfiguration config) throws URISyntaxException {
        this(new URI(config.getOntologyUri()), config);
    }

    /**
     * Construct a new ontology helper instance.
     *
     * @param ontologyUri the URI giving the location of the ontology.
     * @param config the ontology configuration, containing the property URIs
     * for labels, synonyms, etc.
     * @throws URISyntaxException if the URI cannot be parsed.
     */
    public OWLOntologyHelper(URI ontologyUri, OWLOntologyConfiguration config) throws URISyntaxException {
        this.config = config;

        if (!ontologyUri.isAbsolute()) {
            // Try to read as a file from the resource path
            LOGGER.debug("Ontology URI {} is not absolute - loading from classpath", ontologyUri);
            URL fileUrl = this.getClass().getClassLoader().getResource(ontologyUri.toString());
            if (fileUrl != null) {
                ontologyUri = fileUrl.toURI();
            } else {
                throw new URISyntaxException(ontologyUri.toString(), "Could not build URL for file");
            }
        }

        this.dataManager = new OWLDataManager(ontologyUri);
    }

    @Override
    public void updateLastCallTime() {
        this.lastCallTime = System.currentTimeMillis();
    }

    @Override
    public long getLastCallTime() {
        return lastCallTime;
    }

    @Override
    public void dispose() {
        dataManager.dispose();

        // Empty caches
        labels.clear();
        synonyms.clear();
        definitions.clear();
    }

    @Override
    protected OntologyHelperConfiguration getConfiguration() {
        return config;
    }

    @Override
    public boolean isIriInOntology(String iri) throws OntologyHelperException {
        return dataManager.isIriInOntology(IRI.create(iri));
    }

    @Override
    public Collection<String> findLabels(String iri) throws OntologyHelperException {
        return findLabels(dataManager.getOntology(), IRI.create(iri));
    }

    @Override
    public Collection<String> findLabelsForIRIs(Collection<String> iris) throws OntologyHelperException {
        Set<String> labels = new HashSet<>();
        OWLOntology ontology = dataManager.getOntology();
        iris.stream().map(iri -> findLabels(ontology, IRI.create(iri))).forEach(labels::addAll);
        return labels;
    }

    @Override
    public Collection<String> findSynonyms(String iri) throws OntologyHelperException {
        return findSynonyms(IRI.create(iri));
    }

    @Override
    public Collection<String> findDefinitions(String iri) throws OntologyHelperException {
        return findDefinitions(IRI.create(iri));
    }

    private Collection<String> findLabels(OWLOntology ontology, IRI iri) {
        if (!labels.containsKey(iri)) {
            Collection<String> classNames = findPropertyValueStrings(ontology, config.getLabelPropertyUris(), iri);
            labels.put(iri, classNames);
        }
        return labels.get(iri);
    }

    private Collection<String> findSynonyms(IRI iri) throws OntologyHelperException {
        if (!synonyms.containsKey(iri)) {
            Collection<String> classNames = findPropertyValueStrings(dataManager.getOntology(),
                    config.getSynonymPropertyUris(), iri);
            synonyms.put(iri, classNames);
        }
        return synonyms.get(iri);
    }

    private Collection<String> findDefinitions(IRI iri) throws OntologyHelperException {
        if (!definitions.containsKey(iri)) {
            Collection<String> classNames = findPropertyValueStrings(dataManager.getOntology(),
                    config.getDefinitionPropertyUris(), iri);
            definitions.put(iri, classNames);
        }
        return definitions.get(iri);
    }

    private Collection<String> findPropertyValueStrings(OWLOntology ontology, List<String> propertyUris, IRI iri) {
        Collection<String> classNames = new HashSet<>();

        OWLDataFactory odf = ontology.getOWLOntologyManager().getOWLDataFactory();

        // For every property URI, find the annotations for this entry
        propertyUris.stream().map(IRI::create).map(odf::getOWLAnnotationProperty)
                .map(prop -> findAnnotationNames(ontology, iri, prop)).forEach(classNames::addAll);

        return classNames;
    }

    private Collection<String> findAnnotationNames(OWLOntology ontology, IRI iri,
            OWLAnnotationProperty annotationType) {
        Collection<String> classNames = new HashSet<>();

        // get all literal annotations
        ontology.getAnnotationAssertionAxioms(iri).forEach(axiom -> {
            if (axiom.getAnnotation().getProperty().equals(annotationType)) {
                OWLAnnotationValue value = axiom.getAnnotation().getValue();
                Optional<String> name = getOWLAnnotationValueAsString(value);
                if (name.isPresent()) {
                    classNames.add(name.get());
                }
            }
        });

        return classNames;
    }

    private Optional<String> getOWLAnnotationValueAsString(OWLAnnotationValue value) {
        if (value instanceof IRI) {
            Optional<String> shortForm = getShortForm((IRI) value);
            if (shortForm.isPresent()) {
                return shortForm;
            }
        } else if (value instanceof OWLLiteral) {
            return Optional.of(((OWLLiteral) value).getLiteral());
        }
        return Optional.empty();
    }

    private static Optional<String> getShortForm(IRI entityIRI) {
        LOGGER.trace("Attempting to extract fragment name of URI '" + entityIRI + "'");
        String termURI = entityIRI.toString();
        URI entUri = entityIRI.toURI();

        // we want the "final part" of the URI...
        if (!StringUtils.isEmpty(entUri.getFragment())) {
            // a uri with a non-null fragment, so use this...
            LOGGER.trace("Extracting fragment name using URI fragment (" + entUri.getFragment() + ")");
            return Optional.of(entUri.getFragment());
        } else if (entityIRI.toURI().getPath() != null) {
            // no fragment, but there is a path so try and extract the final
            // part...
            if (entityIRI.toURI().getPath().contains("/")) {
                LOGGER.trace("Extracting fragment name using final part of the path of the URI");
                return Optional.of(
                        entityIRI.toURI().getPath().substring(entityIRI.toURI().getPath().lastIndexOf('/') + 1));
            } else {
                // no final path part, so just return whole path
                LOGGER.trace("Extracting fragment name using the path of the URI");
                return Optional.of(entityIRI.toURI().getPath());
            }
        } else {
            // no fragment, path is null, we've run out of rules so don't
            // shorten
            LOGGER.trace("No rules to shorten this URI could be found (" + termURI + ")");
            return Optional.empty();
        }
    }

    @Override
    public Collection<String> getChildIris(String iri) throws OntologyHelperException {
        return getSubclassUris(dataManager.getOWLClass(IRI.create(iri)), true);
    }

    @Override
    public Collection<String> getDescendantIris(String iri) throws OntologyHelperException {
        return getSubclassUris(dataManager.getOWLClass(IRI.create(iri)), false);
    }

    @Override
    public Collection<String> getParentIris(String iri) throws OntologyHelperException {
        return getSuperclassUris(dataManager.getOWLClass(IRI.create(iri)), true);
    }

    @Override
    public Collection<String> getAncestorIris(String iri) throws OntologyHelperException {
        return getSuperclassUris(dataManager.getOWLClass(IRI.create(iri)), false);
    }

    private Collection<String> getSubclassUris(OWLClass owlClass, boolean direct) throws OntologyHelperException {
        if (owlClass == null) {
            return Collections.emptySet();
        }
        return getUrisFromNodeSet(dataManager.getReasoner().getSubClasses(owlClass, direct));
    }

    private Collection<String> getSuperclassUris(OWLClass owlClass, boolean direct) throws OntologyHelperException {
        if (owlClass == null) {
            return Collections.emptySet();
        }
        return getUrisFromNodeSet(dataManager.getReasoner().getSuperClasses(owlClass, direct));
    }

    private Collection<String> getUrisFromNodeSet(NodeSet<OWLClass> nodeSet) {
        Set<String> uris = new HashSet<>();

        for (Node<OWLClass> node : nodeSet) {
            uris.addAll(extractIris(node));
        }

        return uris;
    }

    private Collection<String> extractIris(Node<OWLClass> node) {
        return node.getEntities().stream().filter(this::isClassSatisfiable).map(OWLClass::getIRI).map(IRI::toString)
                .collect(Collectors.toSet());
    }

    private boolean isClassSatisfiable(OWLClass owlClass) {
        return !owlClass.isAnonymous() && !owlClass.getIRI().isNothing();
    }

    @Override
    public Map<String, Collection<String>> getRelations(String iri) throws OntologyHelperException {
        Map<String, Collection<String>> restrictions = new HashMap<>();

        OWLOntology ontology = dataManager.getOntology();
        OWLClass owlClass = dataManager.getOWLClass(IRI.create(iri));
        if (owlClass != null) {
            RestrictionVisitor visitor = new RestrictionVisitor(Collections.singleton(ontology));
            for (OWLSubClassOfAxiom ax : ontology.getSubClassAxiomsForSubClass(owlClass)) {
                OWLClassExpression superCls = ax.getSuperClass();
                // Ask our superclass to accept a visit from the RestrictionVisitor
                // - if it is an existential restriction then our restriction visitor
                // will answer it - if not our visitor will ignore it
                superCls.accept(visitor);
            }

            for (OWLObjectSomeValuesFrom val : visitor.getSomeValues()) {
                OWLClassExpression exp = val.getFiller();

                // Get the shortname of the property expression
                String shortForm = null;
                Set<OWLObjectProperty> signatureProps = val.getProperty().getObjectPropertiesInSignature();
                for (OWLObjectProperty sigProp : signatureProps) {
                    Collection<String> labels = findLabels(ontology, sigProp.getIRI());
                    if (labels.size() > 0) {
                        shortForm = new ArrayList<>(labels).get(0);
                    }
                }

                if (shortForm != null && !exp.isAnonymous()) {
                    IRI expIri = exp.asOWLClass().getIRI();

                    if (!restrictions.containsKey(shortForm)) {
                        restrictions.put(shortForm, new ArrayList<>());
                    }
                    restrictions.get(shortForm).add(expIri.toString());
                }
            }
        }

        return restrictions;
    }

}