de.uni_rostock.goodod.owl.OntologyCache.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_rostock.goodod.owl.OntologyCache.java

Source

/**
  Copyright (C) 2011 The University of Rostock.
     
  Written by:  Niels Grewe <niels.grewe@uni-rostock.de>
  Created: 20.12.2011
      
  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.
    
  You should have received a copy of the GNU General Public
  License along with this program; see the file COPYING.
  If not, write to the Free Software Foundation,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    
 */
package de.uni_rostock.goodod.owl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.FileDocumentSource;
import org.semanticweb.owlapi.model.*;

import de.uni_rostock.goodod.owl.normalization.NormalizerFactory;

import java.io.File;
import java.net.URI;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Niels Grewe <niels.grewe@uni-rostock.de>
 *
 */
public class OntologyCache {

    private final int threadCount;
    private ExecutorService executor;
    private final OWLOntologyLoaderConfiguration config;
    private final Set<? extends OWLOntologyIRIMapper> mappers;
    private final Map<URI, FutureTask<OWLOntology>> futures;
    private static Log logger = LogFactory.getLog(OntologyCache.class);
    private static OntologyCache sharedCache;
    private NormalizerFactory normalizerFactory;
    private AtomicInteger pendingFutures;
    static public IRI originallyDefinedIRI = IRI
            .create("http://www.iph.uni-rostock.de/goodod/autogen.owl#originallyDefined");

    public static synchronized OntologyCache getSharedCache() {
        return sharedCache;
    }

    public static synchronized OntologyCache setupSharedCache(Set<? extends OWLOntologyIRIMapper> IRIMappers,
            Set<IRI> importsToIgnore, int threads) {
        if (null == sharedCache) {
            sharedCache = new OntologyCache(IRIMappers, importsToIgnore, threads);
        }
        return sharedCache;
    }

    public OntologyCache(Set<? extends OWLOntologyIRIMapper> IRIMappers, Set<IRI> importsToIgnore, int threads) {
        threadCount = threads;
        pendingFutures = new AtomicInteger(0);
        executor = Executors.newFixedThreadPool(threadCount);
        OWLOntologyLoaderConfiguration interimConfig = new OWLOntologyLoaderConfiguration();

        for (IRI theIRI : importsToIgnore) {
            interimConfig = interimConfig.addIgnoredImport(theIRI);
        }
        interimConfig = interimConfig.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
        config = interimConfig;
        mappers = IRIMappers;
        futures = new HashMap<URI, FutureTask<OWLOntology>>(24);
    }

    public OWLOntology getOntologySynchronouslyAtURI(URI theURI) throws OWLOntologyCreationException {
        OWLOntology ontology = null;
        FutureTask<OWLOntology> ontologyFuture = getOntologyFutureAtURI(theURI);
        try {
            ontology = ontologyFuture.get();
        } catch (Throwable e) {
            logger.warn("Could not load ontology", e);
        }

        return ontology;
    }

    private synchronized void futureDone() {
        pendingFutures.decrementAndGet();
    }

    public synchronized void removeOntologyAtURI(URI u) {
        FutureTask<OWLOntology> future = futures.get(u);
        if (null == future) {
            return;
        } else if (false == future.isDone()) {
            future.cancel(true);
        }
        futures.remove(u);
    }

    public synchronized void flushCache() {
        for (Entry<URI, FutureTask<OWLOntology>> f : futures.entrySet()) {
            FutureTask<OWLOntology> future = f.getValue();
            if (false == future.isDone()) {
                future.cancel(true);
            }
        }
        futures.clear();
    }

    public FutureTask<OWLOntology> getOntologyAtURI(URI theURI) throws OWLOntologyCreationException {
        int waitCount = 0;
        while (pendingFutures.get() > threadCount) {
            if (0 == ++waitCount % 8) {

                /* 
                 * Thight loop a few times, then yield in order to let
                 * the other threads finish.
                 */
                Thread.yield();
            }
        }
        return getOntologyFutureAtURI(theURI);
    }

    private synchronized FutureTask<OWLOntology> getOntologyFutureAtURI(final URI u)
            throws OWLOntologyCreationException {
        FutureTask<OWLOntology> future = null;

        future = futures.get(u);
        if (null != future) {
            return future;
        }
        future = new FutureTask<OWLOntology>(new Callable<OWLOntology>() {
            public OWLOntology call() throws ExecutionException {
                OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
                if (null != mappers) {
                    for (OWLOntologyIRIMapper m : mappers) {
                        manager.addIRIMapper(m);
                    }
                }
                FileDocumentSource source = new FileDocumentSource(new File(u));
                OWLOntology ontology;
                try {
                    ontology = manager.loadOntologyFromOntologyDocument(source, config);
                    markOriginalClasses(ontology);
                    logger.info("Loading and normalizing ontology from " + u.toString() + ".");
                    if (null != normalizerFactory) {
                        normalizerFactory.normalize(ontology);
                    }
                } catch (OWLOntologyCreationException e) {
                    throw new ExecutionException(e);
                }
                // Mark this future as done.
                futureDone();
                return ontology;
            }
        });
        futures.put(u, future);
        // We track our pending futures
        pendingFutures.incrementAndGet();
        executor.execute(future);

        return future;
    }

    /**
     * Adds annotations to all classes defined in the ontology, stating that
     * they originally belong to the ontology. 
     * 
     * @param ontology The ontology to mark up.
     */
    private void markOriginalClasses(OWLOntology ontology) {
        OWLOntologyManager manager = ontology.getOWLOntologyManager();
        OWLDataFactory factory = manager.getOWLDataFactory();
        OWLAnnotationProperty prop = factory.getOWLAnnotationProperty(originallyDefinedIRI);
        OWLAnnotationValue theTrue = factory.getOWLLiteral(true);
        for (OWLClass c : ontology.getClassesInSignature(false)) {
            OWLAnnotationAssertionAxiom ax = factory.getOWLAnnotationAssertionAxiom(prop, c.getIRI(), theTrue);
            manager.addAxiom(ontology, ax);
        }
    }

    public void setNormalizerFactory(NormalizerFactory n) {
        normalizerFactory = n;

    }

    public NormalizerFactory getNormalizerFactory() {
        return normalizerFactory;
    }

    public OWLOntologyLoaderConfiguration getOntologyLoaderConfiguration() {
        return config;
    }

    public void teardown() {
        flushCache();
        executor.shutdownNow();
        executor = null;

    }

    @Override
    public void finalize() throws Throwable {
        try {
            if (null != executor) {
                executor.shutdownNow();
            }
        } finally {
            super.finalize();
        }
    }
}