/******************************************************************************* * Copyright 2014 Miami-Dade County * * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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 org.sharegov.cirmx.maintenance; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import org.semanticweb.owlapi.model.AxiomType; import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLEntity; import org.semanticweb.owlapi.model.OWLIndividual; import org.semanticweb.owlapi.model.OWLNamedIndividual; import org.semanticweb.owlapi.model.OWLObjectProperty; import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom; import org.semanticweb.owlapi.model.OWLOntology; import org.sharegov.cirm.OWL; import org.sharegov.cirm.StartUp; import org.sharegov.cirm.owl.OWLEntityCondition; /** * OntologyGraphSearch finds all axioms connected to a non-builtin entity (e.g. an SR) by depth first search from subject to object. * No reasoner involved. * * Connected means starting from the given non-builtin entity, all axioms are returned that can be reached by DFS. * Builtin Entities such as OWLDatatypes are not explored! * * StopExpansionCondition may contain either NamedIndiviuals that should not be expanded, or ObjectProperties, whose objects should not be expanded. * reverseTraversalObjectProperties will expand from object to subject. * * @author Thomas Hilpold (CIAO/Miami-Dade County) * @created Oct 5, 2012 */ public class OntologyGraphSearch { Map<OWLEntity, Set<OWLAxiom>> entityToAxioms; public List<OWLAxiom> findAllConnectedDFS(final OWLOntology onto, final OWLEntity e) { return findAllConnectedDFS(onto, e, new OWLEntityCondition() { @Override public boolean isMetByNone(Set<? extends OWLEntity> es) { return true; } @Override public boolean isMetByAll(Set<? extends OWLEntity> es) { return false; } @Override public boolean isMet(OWLEntity e) { return false; } }, new HashSet<OWLObjectProperty>()); } /** * Stops at Datatypes. * @param onto * @param i * @return a list with unique axioms that are connected to e. (builtin entities ignored) */ public List<OWLAxiom> findAllConnectedDFS(final OWLOntology onto, final OWLEntity e, final OWLEntityCondition stopExpansionCondition, final Set<OWLObjectProperty> reverseTraversalObjectProperties) { prepareGraph(onto); Set<OWLEntity> exploredE = new HashSet<OWLEntity>(entityToAxioms.size()); List<OWLAxiom> orderedResult = new ArrayList<OWLAxiom>(entityToAxioms.size()/2); findAllConnectedDFS(e, stopExpansionCondition, reverseTraversalObjectProperties, exploredE, orderedResult); return orderedResult; } protected void findAllConnectedDFS(final OWLEntity e, final OWLEntityCondition stopExpansionCondition, final Set<OWLObjectProperty> reverseTraversalObjectProperties, Set<OWLEntity> exploredE, List<OWLAxiom> result) { if (!shouldExplore(e, stopExpansionCondition)) return; exploredE.add(e); System.out.println("Exploring: " + e); Set<OWLAxiom> eAxioms = entityToAxioms.get(e); if (eAxioms == null) { System.err.println("findAllConnectedDFS: No axioms by entity: " + e.toStringID()); return; } for (OWLAxiom ax : eAxioms) { if (ax.getAxiomType().equals(AxiomType.OBJECT_PROPERTY_ASSERTION)) { OWLObjectPropertyAssertionAxiom oax = (OWLObjectPropertyAssertionAxiom)ax; //Expecting all named: OWLObjectProperty op = oax.getProperty().isAnonymous()? null : oax.getProperty().asOWLObjectProperty(); if (oax.getSubject().equals(e)) { if (!result.contains(ax)) { System.out.println("Added opa: " + ax); result.add(ax); } //else don't add OPA where e is object //Check if we shall traverse down this OPA to expand the object. OWLNamedIndividual object = (OWLNamedIndividual)((OWLObjectPropertyAssertionAxiom)ax).getObject(); if (!stopExpansionCondition.isMet(object) && !stopExpansionCondition.isMet(op)) { if (!exploredE.contains(object)) { findAllConnectedDFS(object, stopExpansionCondition, reverseTraversalObjectProperties, exploredE, result); } } } else if (op != null && oax.getObject().equals(e) && reverseTraversalObjectProperties.contains(op)) { OWLNamedIndividual subject = (OWLNamedIndividual)((OWLObjectPropertyAssertionAxiom)ax).getSubject(); if (!exploredE.contains(subject)) { findAllConnectedDFS(subject, stopExpansionCondition, reverseTraversalObjectProperties, exploredE, result); } } } else { // add class assertions, data prop, et.c. for e. if (!result.contains(ax)) { System.out.println(ax); result.add(ax); } } } } /** * @param e * @return */ public boolean shouldExplore(final OWLEntity e, final OWLEntityCondition stopExpansionCondition) { return !e.isBuiltIn() && e.isOWLNamedIndividual() && !stopExpansionCondition.isMet(e); } private void prepareGraph(OWLOntology onto) { Set<OWLAxiom> allAxioms = onto.getAxioms(); entityToAxioms = new HashMap<OWLEntity, Set<OWLAxiom>>(allAxioms.size() * 2); for (OWLAxiom ax : allAxioms) { Set<OWLEntity> sig = ax.getSignature(); for (OWLEntity e : sig) { Set<OWLAnnotationAssertionAxiom> annotations = e.getAnnotationAssertionAxioms(onto); Set<OWLAxiom> eAxioms = entityToAxioms.get(e); if (eAxioms == null) { eAxioms = new HashSet<OWLAxiom>(); entityToAxioms.put(e, eAxioms); } eAxioms.add(ax); eAxioms.addAll(annotations); } } } public static Set<OWLIndividual> findSubjectsOfObject(OWLNamedIndividual ind, OWLOntology O) { Set<OWLIndividual> result = new HashSet<OWLIndividual>(); for (OWLAxiom ax:ind.getReferencingAxioms(O)) { if (! (ax instanceof OWLObjectPropertyAssertionAxiom)) continue; OWLObjectPropertyAssertionAxiom oax = (OWLObjectPropertyAssertionAxiom)ax; if (oax.getObject().equals(ind)) result.add(oax.getSubject()); } return result; } public static Set<OWLIndividual> findObjectsOfSubject(OWLNamedIndividual ind, OWLOntology O) { Set<OWLIndividual> result = new HashSet<OWLIndividual>(); for (OWLAxiom ax:ind.getReferencingAxioms(O)) { if (! (ax instanceof OWLObjectPropertyAssertionAxiom)) continue; OWLObjectPropertyAssertionAxiom oax = (OWLObjectPropertyAssertionAxiom)ax; if (oax.getSubject().equals(ind)) result.add(oax.getObject()); } return result; } public static void breadthFirstObjectGraph(OWLNamedIndividual ind, OWLOntology O) { Queue<OWLIndividual> toexplore = new LinkedList<OWLIndividual>(); Set<OWLIndividual> examined = new HashSet<OWLIndividual>(); toexplore.add(ind); while (!toexplore.isEmpty()) { OWLIndividual next = toexplore.remove(); examined.add(next); for (OWLIndividual x : findObjectsOfSubject((OWLNamedIndividual)next, O)) { if (!examined.contains(x)) { toexplore.add(x); } } } System.out.println(examined); } public static void main(String []argv) { StartUp.getConfig().set("metaDatabaseLocation", "c:/temp/testontodb_clone"); breadthFirstObjectGraph(OWL.individual("legacy:COMPWPH"), OWL.ontology()); } }