org.dllearner.algorithms.pattern.OWLAxiomPatternFinder.java Source code

Java tutorial

Introduction

Here is the source code for org.dllearner.algorithms.pattern.OWLAxiomPatternFinder.java

Source

/**
 * Copyright (C) 2007 - 2016, Jens Lehmann
 *
 * This file is part of DL-Learner.
 *
 * DL-Learner 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.
 *
 * DL-Learner 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 <http://www.gnu.org/licenses/>.
 */
package org.dllearner.algorithms.pattern;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import org.dllearner.kb.dataset.OWLOntologyDataset;
import org.dllearner.kb.repository.OntologyRepository;
import org.dllearner.kb.repository.OntologyRepositoryEntry;
import org.dllearner.utilities.owl.ManchesterOWLSyntaxOWLObjectRendererImplExt;
import org.ini4j.IniPreferences;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.functional.parser.OWLFunctionalSyntaxOWLParser;
import org.semanticweb.owlapi.functional.renderer.FunctionalSyntaxObjectRenderer;
import org.semanticweb.owlapi.io.OWLObjectRenderer;
import org.semanticweb.owlapi.io.StringDocumentSource;
import org.semanticweb.owlapi.io.UnparsableOntologyException;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.model.parameters.Imports;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.prefs.Preferences;

public class OWLAxiomPatternFinder {

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

    private static Queue<String> classVarQueue = new LinkedList<>();
    private static Queue<String> propertyVarQueue = new LinkedList<>();
    private static Queue<String> individualVarQueue = new LinkedList<>();
    private static Queue<String> datatypeVarQueue = new LinkedList<>();

    static {
        for (int i = 65; i <= 90; i++) {
            classVarQueue.add(String.valueOf((char) i));
        }
        for (int i = 97; i <= 111; i++) {
            individualVarQueue.add(String.valueOf((char) i));
        }
        for (int i = 112; i <= 122; i++) {
            propertyVarQueue.add(String.valueOf((char) i));
        }

    }

    private OntologyRepository repository;
    private OWLOntologyManager manager;
    private OWLDataFactory dataFactory;

    private Connection conn;
    private PreparedStatement selectOntologyIdPs;
    private PreparedStatement insertOntologyPs;
    private PreparedStatement insertOntologyErrorPs;
    private PreparedStatement selectPatternIdPs;
    private PreparedStatement insertPatternIdPs;
    private PreparedStatement insertOntologyPatternPs;

    private OWLObjectRenderer axiomRenderer = new ManchesterOWLSyntaxOWLObjectRendererImplExt();

    private boolean randomOrder = false;

    public OWLAxiomPatternFinder(OWLOntologyDataset dataset) {

    }

    public OWLAxiomPatternFinder(OntologyRepository repository) {
        this.repository = repository;
        manager = OWLManager.createOWLOntologyManager();
        dataFactory = manager.getOWLDataFactory();

        initDBConnection();
        prepare();
    }

    public OWLAxiomPatternFinder(OntologyRepository repository, Connection conn) {
        this.repository = repository;
        this.conn = conn;
        manager = OWLManager.createOWLOntologyManager();
        dataFactory = manager.getOWLDataFactory();

        prepare();
    }

    /**
     * Start the pattern detection.
     */
    public void start() {
        final ExecutorService tp = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1);

        Collection<OntologyRepositoryEntry> entries = repository.getEntries();
        if (randomOrder) {
            List<OntologyRepositoryEntry> entryList = new ArrayList<>(repository.getEntries());
            Collections.shuffle(entryList);
            entries = entryList;
        }

        final Multiset<OWLAxiom> allAxiomPatterns = HashMultiset.create();

        AtomicInteger i = new AtomicInteger(1);

        manager = OWLManager.createConcurrentOWLOntologyManager();

        for (OntologyRepositoryEntry entry : entries) {
            tp.execute(new Runnable() {
                @Override
                public void run() {
                    OWLAxiomRenamer renamer = new OWLAxiomRenamer(dataFactory);

                    System.out.print(i.incrementAndGet() + ": ");
                    URI uri = entry.getPhysicalURI();
                    //               if(uri.toString().startsWith("http://rest.bioontology.org/bioportal/ontologies/download/42764")){
                    if (!ontologyProcessed(uri)) {//if(entry.getOntologyShortName().equals("00698"))continue;
                        LOGGER.info("Loading \"" + entry.getOntologyShortName() + "\" from " + uri);
                        try {

                            OWLOntology ontology = manager.loadOntology(IRI.create(uri));
                            Multiset<OWLAxiom> axiomPatterns = HashMultiset.create();
                            Set<OWLAxiom> logicalAxioms = new HashSet<>();
                            for (AxiomType<?> type : AxiomType.AXIOM_TYPES) {
                                if (type.isLogical()) {
                                    logicalAxioms.addAll(ontology.getAxioms(type, Imports.INCLUDED));
                                }
                            }
                            LOGGER.info(" (" + logicalAxioms.size() + " axioms)");
                            for (OWLAxiom axiom : logicalAxioms) {
                                OWLAxiom renamedAxiom = renamer.rename(axiom);
                                axiomPatterns.add(renamedAxiom);
                            }
                            //                     allAxiomPatterns.addAll(axiomPatterns);
                            addOntologyPatterns(uri, ontology, axiomPatterns);
                            //                     for (OWLAxiom owlAxiom : Multisets.copyHighestCountFirst(allAxiomPatterns).elementSet()) {
                            //                        System.out.println(owlAxiom + ": " + allAxiomPatterns.count(owlAxiom));
                            //                     }
                            manager.removeOntology(ontology);
                        } catch (OWLOntologyAlreadyExistsException e) {
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                            addOntologyError(uri, e);
                        }
                    } else {
                        LOGGER.info("Already processed.");
                    }
                }
            });
        }

        tp.shutdown();
        try {
            // Wait a while for existing tasks to terminate
            if (!tp.awaitTermination(60, TimeUnit.MINUTES)) {
                tp.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!tp.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            tp.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }

    private void prepare() {
        createTables();
        try {
            selectOntologyIdPs = conn.prepareStatement("SELECT id FROM Ontology WHERE url=?");
            insertOntologyPs = conn.prepareStatement(
                    "INSERT INTO Ontology (url, iri, repository, logical_axioms, tbox_axioms, rbox_axioms"
                            + ", abox_axioms, classes, object_properties, data_properties, individuals) VALUES(?,?,?,?,?,?,?,?,?,?,?)");
            insertOntologyErrorPs = conn
                    .prepareStatement("INSERT INTO Ontology (url, iri, repository) VALUES(?,?,?)");
            selectPatternIdPs = conn.prepareStatement("SELECT id FROM Pattern WHERE pattern=?");
            insertPatternIdPs = conn
                    .prepareStatement("INSERT INTO Pattern (pattern,pattern_pretty,axiom_type) VALUES(?,?,?)");
            insertOntologyPatternPs = conn.prepareStatement(
                    "INSERT INTO Ontology_Pattern (ontology_id, pattern_id, occurrences) VALUES(?,?,?)");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private String render(OWLAxiom axiom) {
        try {
            OWLOntologyManager man = OWLManager.createOWLOntologyManager();
            OWLOntology ontology = man.createOntology();
            man.addAxiom(ontology, axiom);
            StringWriter sw = new StringWriter();
            FunctionalSyntaxObjectRenderer r = new FunctionalSyntaxObjectRenderer(ontology, sw);
            axiom.accept(r);
            return sw.toString();
        } catch (OWLOntologyCreationException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void initDBConnection() {
        try {
            InputStream is = this.getClass().getClassLoader()
                    .getResourceAsStream("org/dllearner/algorithms/pattern/db_settings.ini");
            Preferences prefs = new IniPreferences(is);
            String dbServer = prefs.node("database").get("server", null);
            String dbName = prefs.node("database").get("name", null);
            String dbUser = prefs.node("database").get("user", null);
            String dbPass = prefs.node("database").get("pass", null);

            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://" + dbServer + "/" + dbName;
            conn = DriverManager.getConnection(url, dbUser, dbPass);
        } catch (ClassNotFoundException | IOException | SQLException e) {
            e.printStackTrace();
        }
    }

    private void createTables() {
        try {
            Statement statement = conn.createStatement();

            statement.execute("CREATE TABLE IF NOT EXISTS Pattern (" + "id MEDIUMINT NOT NULL AUTO_INCREMENT,"
                    + "pattern TEXT NOT NULL," + "pattern_pretty TEXT NOT NULL,"
                    + "axiom_type VARCHAR(15) NOT NULL," + "PRIMARY KEY(id),"
                    + "INDEX(pattern(1000))) DEFAULT CHARSET=utf8");

            statement.execute("CREATE TABLE IF NOT EXISTS Ontology (" + "id MEDIUMINT NOT NULL AUTO_INCREMENT,"
                    + "url VARCHAR(1000) NOT NULL," + "iri VARCHAR(2000) NOT NULL,"
                    + "repository VARCHAR(200) NOT NULL," + "logical_axioms MEDIUMINT DEFAULT 0,"
                    + "tbox_axioms MEDIUMINT DEFAULT 0," + "rbox_axioms MEDIUMINT DEFAULT 0,"
                    + "abox_axioms MEDIUMINT DEFAULT 0," + "classes MEDIUMINT DEFAULT 0,"
                    + "object_properties MEDIUMINT DEFAULT 0," + "data_properties MEDIUMINT DEFAULT 0,"
                    + "individuals MEDIUMINT DEFAULT 0," + "PRIMARY KEY(id)," + "INDEX(url)) DEFAULT CHARSET=utf8");

            statement.execute("CREATE TABLE IF NOT EXISTS Ontology_Pattern (" + "ontology_id MEDIUMINT NOT NULL,"
                    + "pattern_id MEDIUMINT NOT NULL," + "occurrences INTEGER(8) NOT NULL,"
                    + "FOREIGN KEY (ontology_id) REFERENCES Ontology(id) ON DELETE CASCADE,"
                    + "FOREIGN KEY (pattern_id) REFERENCES Pattern(id) ON DELETE CASCADE,"
                    + "PRIMARY KEY(ontology_id, pattern_id)) DEFAULT CHARSET=utf8");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private int addPattern(OWLAxiom axiom) {
        String axiomString = render(axiom);
        //check for existing entry
        try {
            selectPatternIdPs.setString(1, axiomString);
            ResultSet rs = selectPatternIdPs.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //add pattern entry
        try {
            insertPatternIdPs.setString(1, axiomString);
            insertPatternIdPs.setString(2, axiomRenderer.render(axiom));
            insertPatternIdPs.setString(3, getAxiomType(axiom));
            insertPatternIdPs.execute();
        } catch (SQLException e) {
            System.err.println("Pattern too long for database?" + axiomString.length());
            e.printStackTrace();
        }
        //get the auto generated ID
        try {
            selectPatternIdPs.setString(1, axiomString);
            ResultSet rs = selectPatternIdPs.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }

    private String getAxiomType(OWLAxiom axiom) {
        AxiomType<?> type = axiom.getAxiomType();
        String s;
        if (AxiomType.TBoxAxiomTypes.contains(type)) {
            s = "TBox";
        } else if (AxiomType.RBoxAxiomTypes.contains(type)) {
            s = "RBox";
        } else if (AxiomType.ABoxAxiomTypes.contains(type)) {
            s = "ABox";
        } else {
            System.out.println(axiom + "-" + type);
            //should not happen
            s = "Non-Logical";
        }
        return s;
    }

    private synchronized boolean ontologyProcessed(URI uri) {
        //check if ontology was already processed
        try {
            selectOntologyIdPs.setString(1, uri.toString());
            ResultSet rs = selectOntologyIdPs.executeQuery();
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    private synchronized void addOntologyError(URI physicalURI, Exception ex) {
        String url = physicalURI.toString();
        //add ontology loading/parsing/... error entry
        try {
            insertOntologyErrorPs.setString(1, url);
            String errorMessage = "ERROR:" + ex.getClass().getSimpleName();
            if (!(ex instanceof UnparsableOntologyException)) {
                errorMessage += (ex.getMessage() != null ? ("->" + ex.getMessage()) : "");
            }
            if (errorMessage.length() > 1900) {
                errorMessage = errorMessage.substring(0, 1900);
            }
            insertOntologyErrorPs.setString(2, errorMessage);
            insertOntologyErrorPs.setString(3, repository.getName());
            insertOntologyErrorPs.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private synchronized int addOntology(URI physicalURI, OWLOntology ontology) {
        String url = physicalURI.toString();
        String ontologyIRI = "Anonymous";
        if (!ontology.getOntologyID().isAnonymous()) {
            ontologyIRI = ontology.getOntologyID().getOntologyIRI().toString();
        }
        //check for existing entry
        try {
            selectOntologyIdPs.setString(1, url);
            ResultSet rs = selectOntologyIdPs.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //add ontology entry
        try {
            insertOntologyPs.setString(1, url);
            insertOntologyPs.setString(2, ontologyIRI);
            insertOntologyPs.setString(3, repository.getName());
            Set<OWLAxiom> tbox = ontology.getTBoxAxioms(Imports.INCLUDED);
            Set<OWLAxiom> rbox = ontology.getRBoxAxioms(Imports.INCLUDED);
            Set<OWLAxiom> abox = ontology.getABoxAxioms(Imports.INCLUDED);

            insertOntologyPs.setInt(4, tbox.size() + rbox.size() + abox.size());
            insertOntologyPs.setInt(5, tbox.size());
            insertOntologyPs.setInt(6, rbox.size());
            insertOntologyPs.setInt(7, abox.size());
            insertOntologyPs.setInt(8, ontology.getClassesInSignature(Imports.INCLUDED).size());
            insertOntologyPs.setInt(9, ontology.getObjectPropertiesInSignature(Imports.INCLUDED).size());
            insertOntologyPs.setInt(10, ontology.getDataPropertiesInSignature(Imports.INCLUDED).size());
            insertOntologyPs.setInt(11, ontology.getIndividualsInSignature(Imports.INCLUDED).size());
            insertOntologyPs.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //get the auto generated ID
        try {
            selectOntologyIdPs.setString(1, url);
            ResultSet rs = selectOntologyIdPs.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }

    private synchronized void addOntologyPatterns(URI physicalURI, OWLOntology ontology,
            Multiset<OWLAxiom> patterns) {
        int ontologyId = addOntology(physicalURI, ontology);
        for (OWLAxiom pattern : patterns.elementSet()) {
            try {
                int patternId = addPattern(pattern);
                int occurrences = patterns.count(pattern);
                insertOntologyPatternPs.setInt(1, ontologyId);
                insertOntologyPatternPs.setInt(2, patternId);
                insertOntologyPatternPs.setInt(3, occurrences);
                insertOntologyPatternPs.execute();
            } catch (SQLException e) {
                System.err.println("Adding pattern\n" + pattern + "\nfailed." + e.getMessage());
            }
        }
    }

    public static void main(String[] args) throws Exception {

        String ontologyURL = "ontologyURL";
        OWLOntologyManager man = OWLManager.createOWLOntologyManager();
        OWLDataFactory dataFactory = man.getOWLDataFactory();
        OWLFunctionalDataPropertyAxiom axiom = dataFactory
                .getOWLFunctionalDataPropertyAxiom(dataFactory.getOWLDataProperty(IRI.create("http://ex.org/p")));
        OWLOntology ontology = man.createOntology();
        man.addAxiom(ontology, axiom);
        StringWriter sw = new StringWriter();
        FunctionalSyntaxObjectRenderer r = new FunctionalSyntaxObjectRenderer(ontology, sw);
        axiom.accept(r);
        System.out.println(sw.toString());
        StringDocumentSource s = new StringDocumentSource(
                "Ontology(<http://www.pattern.org>" + sw.toString() + ")");
        OWLFunctionalSyntaxOWLParser p = new OWLFunctionalSyntaxOWLParser();
        OWLOntology newOntology = man.createOntology();
        p.parse(s, newOntology, new OWLOntologyLoaderConfiguration());
        System.out.println(newOntology.getLogicalAxioms());

    }
}