package org.mindswap.swoop.explore; import java.net.URI; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.reasoner.PelletReasoner; import org.mindswap.swoop.reasoner.SwoopReasoner; import org.mindswap.swoop.reasoner.SwoopToldReasoner; import org.mindswap.swoop.renderer.entity.ConciseFormatEntityRenderer; import org.mindswap.swoop.utils.graph.hierarchy.OntologyGraphNode; import org.mindswap.swoop.utils.graph.hierarchy.OntologyWithClassHierarchyGraph; import org.mindswap.swoop.utils.graph.hierarchy.SwoopOntologyVertex; import org.mindswap.swoop.utils.graph.hierarchy.popup.ClassAxiomContainer; import org.mindswap.swoop.utils.graph.hierarchy.popup.ConcisePlainVisitor; import org.mindswap.swoop.utils.graph.hierarchy.popup.SubclassAxiomContainerComparator; import org.mindswap.swoop.utils.owlapi.AxiomCollector; import org.mindswap.swoop.utils.owlapi.OWLDescriptionFinder; import org.semanticweb.owl.impl.model.OWLDataFactoryImpl; import org.semanticweb.owl.impl.model.OWLDisjointClassesAxiomImpl; import org.semanticweb.owl.impl.model.OWLEquivalentClassesAxiomImpl; import org.semanticweb.owl.impl.model.OWLSubClassAxiomImpl; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLClassAxiom; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLDisjointClassesAxiom; import org.semanticweb.owl.model.OWLEquivalentClassesAxiom; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLNot; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLSubClassAxiom; import aterm.pure.ATermApplImpl; public class AxiomExtractor { private Set myOntologies = null; private OWLOntology myOntology = null; private SwoopModel myModel = null; private SwoopReasoner myReasoner = null; private ConciseFormatEntityRenderer myShortform = null; private OWLClass owlThing = null; private OWLClass owlNothing = null; public AxiomExtractor( OWLOntology ont, SwoopModel model, SwoopReasoner reasoner ) { init( ont, model, reasoner ); } private void init( OWLOntology ont, SwoopModel model, SwoopReasoner reasoner ) { try { myModel = model; myShortform = new ConciseFormatEntityRenderer(); myShortform.setSwoopModel( myModel ); myOntologies = new HashSet(); myOntologies.add( ont ); myReasoner = reasoner; owlThing = myReasoner.getOntology().getOWLDataFactory().getOWLThing(); owlNothing = myReasoner.getOntology().getOWLDataFactory().getOWLNothing(); } catch ( OWLException e ) { e.printStackTrace(); } } public Vector extractSubclassAxioms( boolean withReasoner ) { // use a sorted set Set subclassAxioms = new TreeSet( SubclassAxiomContainerComparator.getInstance() ); try { for (Iterator it = myOntologies.iterator(); it.hasNext(); ) { OWLOntology ont = (OWLOntology)it.next(); myModel.setSelectedOntology( ont ); try { if ( withReasoner ) // load pellet for each ontology { System.err.println("AxiomExtractor: setting Pellet reasoner"); PelletReasoner reasoner = new PelletReasoner(); // use pellet. Place it in model's reasonerCache. myModel.setReasonerWithThreadBlock( reasoner ); myReasoner = myModel.getReasonerCache().getReasoner(ont, reasoner.getName() ); } else // use told reasoner { System.err.println("AxiomExtractor: setting told reasoner"); SwoopToldReasoner reasoner = new SwoopToldReasoner(); myModel.setReasoner( reasoner ); myReasoner = myModel.getReasonerCache().getReasoner(ont, reasoner.getName() ); } } catch ( Exception e ) { System.err.println("** Cannot set reasoner **"); e.printStackTrace(); } OWLClass owlThing = ont.getOWLDataFactory().getOWLThing(); OWLDataFactoryImpl factory = (OWLDataFactoryImpl)ont.getOWLDataFactory(); Set classSet = ont.getClasses(); for (Iterator iter = classSet.iterator(); iter.hasNext(); ) { OWLClass clazz = (OWLClass)iter.next(); Set supers = OWLDescriptionFinder.getSuperClasses(clazz, Collections.singleton(ont)); //if(myReasoner.isConsistent(clazz)) //{ // remove all the named classes because reasoner will eventually add them Iterator iterator = supers.iterator(); while(iterator.hasNext()) if(iterator.next() instanceof OWLClass) iterator.remove(); // add all the named superclasses (including inferred) supers.addAll(myReasoner.superClassesOf(clazz)); // remove owl:Thing from the superclass set iterator = supers.iterator(); while(iterator.hasNext()) { Object o = iterator.next(); if(o instanceof Set && ((Set)o).contains(owlThing)) iterator.remove(); else { OWLDescription desc = null; if ( o instanceof Set) { desc = (OWLDescription)((Set)o).iterator().next(); } else desc = (OWLDescription)o; subclassAxioms.add( new ClassAxiomContainer( new OWLSubClassAxiomImpl( factory, (OWLDescription)clazz, desc), myShortform, myModel )); } } //} } } // return the sorted Vector return new Vector( subclassAxioms ); } catch (OWLException ex) { ex.printStackTrace(); } return null; } /* * extracts class axioms in the import closure of the currently selected ontology in Swoop * */ public Vector extractClassAxioms( ) { // maps a class/class expression (key) to its set of equivalent classes/class expressions (values) // each equivvalent set contains the key as well. Hashtable equivalenceMap = new Hashtable(); // use a sorted set Set classAxiomContainers = new TreeSet( SubclassAxiomContainerComparator.getInstance() ); try { Set importClosure = myReasoner.getOntologies(); /* for each ontology in the import closure * find all told class axioms */ for ( Iterator ontIter = importClosure.iterator(); ontIter.hasNext(); ) { OWLOntology ont = (OWLOntology)ontIter.next(); Set axioms = AxiomCollector.axiomize( ont ); for ( Iterator it = axioms.iterator(); it.hasNext(); ) { Object obj = it.next(); if ( (obj instanceof OWLClassAxiom)) { if ( obj instanceof OWLEquivalentClassesAxiom) { OWLEquivalentClassesAxiom qui = (OWLEquivalentClassesAxiom)obj; Set equivalentClasses = qui.getEquivalentClasses(); if ( equivalentClasses.size() == 1 ) continue; else { addToEquivalents( equivalenceMap, (HashSet)equivalentClasses ); } } else //subclass or disjoint axioms classAxiomContainers.add( new ClassAxiomContainer( (OWLClassAxiom)obj, myShortform, myModel ) ); } } } /* * now get the inferred axioms * */ for ( Iterator ontIter = importClosure.iterator(); ontIter.hasNext(); ) { OWLOntology ont = (OWLOntology)ontIter.next(); OWLDataFactoryImpl factory = (OWLDataFactoryImpl)ont.getOWLDataFactory(); for ( Iterator classIter = ont.getClasses().iterator(); classIter.hasNext(); ) { OWLClass c = (OWLClass)classIter.next(); // superclasses Set supers = c.getSuperClasses( importClosure ); if( myReasoner.isConsistent(c) ) { supers.addAll( myReasoner.superClassesOf(c)); // remove owl:Thing from the superclass set for (Iterator i = supers.iterator(); i.hasNext(); ) { Object o = i.next(); if(o instanceof Set && ((Set)o).contains(owlThing)) i.remove(); else { OWLDescription desc = null; if ( o instanceof Set) desc = (OWLDescription)((Set)o).iterator().next(); else desc = (OWLDescription)o; classAxiomContainers.add( new ClassAxiomContainer( new OWLSubClassAxiomImpl( factory, (OWLDescription)c, desc), myShortform, myModel )); } } } // equivalents ( intersections, unions, enumerations ) Set equivalences = new HashSet(); equivalences.add( c ); if ( myReasoner.isConsistent(c) ) { // get all named equivalent classes (intersections, unions, enumerations ) Set reasonedEquiSet = myReasoner.equivalentClassesOf(c); equivalences.addAll( reasonedEquiSet ); // get complements classes (and make them into OWLNot, so they are equivalent to c) Set reasonedCompSet = myReasoner.complementClassesOf( c ); for ( Iterator it = reasonedCompSet.iterator(); it.hasNext(); ) { OWLClass desc = (OWLClass)it.next(); OWLNot complement = factory.getOWLNot( desc ); equivalences.add( complement ); } } else // if not consistent, it is equivalent to owlNothing { equivalences.add(owlNothing); } // only add to equivalenceMap if #equivalent classes is greater than 1 // ( only one means itself -- "A equivalentTo A") if ( equivalences.size() > 1 ) { addToEquivalents( equivalenceMap, (HashSet)equivalences ); } /* get all named disjoint classes for class 'c' * if c is inconsistent, then nothing is done * if c is consistent, then * - retrieave all disjoint classes from reasoner * */ HashSet disjointsForClass = new HashSet(); if ( myReasoner.isConsistent(c) ) { Set dis = myReasoner.disjointClassesOf( c ); for (Iterator it = dis.iterator(); it.hasNext(); ) { Set classes = (Set)it.next(); // only get the first class, since the rest are equivalents Iterator iter = classes.iterator(); OWLClass aClass = (OWLClass)iter.next(); // add to set only if cClass is consistent if ( myReasoner.isConsistent(aClass) ) disjointsForClass.add( aClass ); } } // now refine disjointsForClass so that every class in disjointsForClass // is not subsumed by another member in set. findRootDisjoints( disjointsForClass ); // now go over the disjointsForClass set and add disjoint axioms for ( Iterator it = disjointsForClass.iterator(); it.hasNext(); ) { OWLClass aClass = (OWLClass)it.next(); HashSet mutuallyDisjointClasses = new HashSet(); mutuallyDisjointClasses.add( c ); mutuallyDisjointClasses.add( aClass ); classAxiomContainers.add( new ClassAxiomContainer( new OWLDisjointClassesAxiomImpl( factory, mutuallyDisjointClasses ), myShortform, myModel )); } } // build equivalence axioms from equivalence maps for ( Iterator it = equivalenceMap.keySet().iterator(); it.hasNext(); ) { OWLDescription desc = (OWLDescription)it.next(); Set equivalentClasses = (Set)equivalenceMap.get( desc ); classAxiomContainers.add( new ClassAxiomContainer( new OWLEquivalentClassesAxiomImpl( factory, equivalentClasses ), myShortform, myModel )); } } return new Vector( classAxiomContainers ); } catch (Exception ex) { ex.printStackTrace(); } return null; } /* * PRIVATE helper methods */ /* Given a set of equivalent classes/expressions, merge them into known ones if known ones * exist. If not, create new places for them in the equivalenceMap * */ private void addToEquivalents( Hashtable equivalenceMap, HashSet equivalentClasses ) throws OWLException { // equiClone only used for iterating through the equivalentClasses set HashSet equiClone = (HashSet)equivalentClasses.clone(); for ( Iterator eqIt = equiClone.iterator(); eqIt.hasNext(); ) { OWLDescription desc = (OWLDescription)eqIt.next(); // ConcisePlainVisitor walker = new ConcisePlainVisitor( myShortform, myModel ); // check to see if desc already in map as key if ( equivalenceMap.keySet().contains( desc ) ) { // desc.accept( walker ); // String descStr = walker.result(); // walker.reset(); // System.err.println("adding additional equivalentClasses of [" + descStr +"]" ); Set oldEquiSet = (Set)equivalenceMap.get( desc ); /* for ( Iterator it = oldEquiSet.iterator(); it.hasNext(); ) { OWLDescription equiDesc = (OWLDescription)it.next(); equiDesc.accept( walker ); String someDesc = walker.result(); walker.reset(); System.err.println(" [o] equivalent to [" + someDesc +"]" ); } for ( Iterator it = equivalentClasses.iterator(); it.hasNext(); ) { OWLDescription equiDesc = (OWLDescription)it.next(); equiDesc.accept( walker ); String someDesc = walker.result(); walker.reset(); System.err.println(" [n] equivalent to [" + someDesc +"]" ); } */ addKnownEquivalences( equivalenceMap, oldEquiSet, equivalentClasses ); // for the updated oldEquiSet, update to its members for ( Iterator it = oldEquiSet.iterator(); it.hasNext(); ) { Object obj = it.next(); equivalenceMap.put( obj, oldEquiSet ); } //equivalentClasses.addAll( oldEquiSet ); //equivalenceMap.put( desc, oldEquiSet ); } else { // not in map, construct a new set, find // known euivalent classes of equivalent classes, // and put those in the new set. Set newEquivalences = new HashSet(); newEquivalences.addAll( equivalentClasses ); // desc.accept( walker ); // String descStr = walker.result(); // walker.reset(); // System.err.println("adding new equivalentClasses of [" + descStr +"]" ); addKnownEquivalences( equivalenceMap, newEquivalences, equivalentClasses ); // System.err.println(" * putting in map with set of size " + newEquivalences.size() ); // for the updated newEquivalences, update to its members for ( Iterator it = newEquivalences.iterator(); it.hasNext(); ) { Object obj = it.next(); equivalenceMap.put( obj, newEquivalences ); } equivalenceMap.put( desc, newEquivalences ); } } } /* * Given the equivalenceMap, a set of known equivalences, and a set of new equivalences. * for each member X of new equivalence, attempts to find to see if it already is registered * in the map. If it is, then find the existing equivalent set for that member from the * map (calling 'get'). Add the members of the existing equivalences to known equivalences, * and update the Map for X. * */ private void addKnownEquivalences( Hashtable equivalenceMap, Set knownEquivalences, Set equivalentClasses ) throws OWLException { // ConcisePlainVisitor walker = new ConcisePlainVisitor( myShortform, myModel ); // System.err.println(" adding known euqivalences"); // for each equivalent class, find if it exists already in equivalenceMap. // if it does, then we get its known equivalent classes and add to newEquivalences // set its equivalent set to this newEquivalences set for ( Iterator it = equivalentClasses.iterator(); it.hasNext(); ) { OWLDescription equiDesc = (OWLDescription)it.next(); // equiDesc.accept( walker ); // String equiStr = walker.result(); // walker.reset(); // System.err.println(" equivalent to: [" + equiStr +"]" ); if ( equivalenceMap.keySet().contains( equiDesc ) ) { Set knownEquiSet = (Set)equivalenceMap.get( equiDesc ); // System.err.println(" ["+ equiStr +"] exists in map, with old size = " + knownEquiSet.size() ); knownEquivalences.addAll( knownEquiSet ); equivalenceMap.put( equiDesc, knownEquivalences ); // System.err.println(" ["+ equiStr +"] exists in map, with new size = " + newEquivalences.size() ); } } } /* * refine input disjointsForClass so that every class in disjointsForClass * is not subsumed by another member in set. */ private void findRootDisjoints( HashSet disjointsForClass ) throws OWLException { HashSet subclassSet = new HashSet(); for ( Iterator it = disjointsForClass.iterator(); it.hasNext(); ) { OWLClass iClass = (OWLClass)it.next(); if ( subclassSet.contains( iClass ) ) // if is already known to be a subclass, then don't process it continue; for ( Iterator jt = disjointsForClass.iterator(); jt.hasNext(); ) { OWLClass jClass = (OWLClass)jt.next(); if ( !myReasoner.isEquivalentClass( jClass, iClass) ) { if ( myReasoner.isSubClassOf(jClass, iClass) ) { //System.out.println( " -" + myShortform.shortForm(jClass.getURI())+ " subsumed by " + myShortform.shortForm(iClass.getURI())); subclassSet.add( jClass ); } } } } disjointsForClass.removeAll( subclassSet ); } }