/* * Created on Sep 19, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package org.mindswap.swoop.utils.graph.hierarchy; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.util.Collection; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import java.util.Vector; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.reasoner.SwoopReasoner; import org.mindswap.swoop.utils.graph.hierarchy.colors.GraphColorScheme; import org.mindswap.swoop.utils.graph.hierarchy.helpers.ClassByRestrictionFinder; import org.mindswap.swoop.utils.owlapi.OWLDescriptionFinder; import org.semanticweb.owl.model.OWLAnd; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLEnumeration; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLOr; import org.semanticweb.owl.model.OWLRestriction; import edu.uci.ics.jung.graph.impl.DirectedSparseGraph; /** * @author Dave Wang * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class OverlayGraph implements OntologyVisualizationViewer.Paintable { protected class OverlayEdge { public ClassTreeNode mySource = null; public ClassTreeNode myDestination = null; public OverlayEdge( ClassTreeNode src, ClassTreeNode dest ) { mySource = src; myDestination = dest; } public String toString() { return mySource.getURI() + "-" + myDestination.getURI(); } public int hashCode() { return this.toString().hashCode(); } public boolean equals(Object obj) { if (!(obj instanceof OverlayEdge)) return false; return (obj.hashCode() == this.hashCode()); } public void paint( Graphics2D g) { AffineTransform oldTransform = g.getTransform(); Stroke oldStroke = g.getStroke(); double x1 = mySource.getGlobalX(); double y1 = mySource.getGlobalY(); double x2 = myDestination.getGlobalX(); double y2 = myDestination.getGlobalY(); int srcRadius = mySource.getRadius(); int destRadius = myDestination.getRadius(); double xdiff = x2 - x1; double ydiff = y2 - y1; double full_length = Math.sqrt( Math.pow(xdiff, 2) + Math.pow(ydiff, 2) ); double phi = Math.acos( xdiff/full_length); double theta = 0; //System.out.println("("+x1+","+y1+"); ("+x2+","+y2+")"); //System.out.println("phi = " + phi); if ( ydiff == 0 ) // slope is infinite { if ( y1 > y2) theta = 0.5 * Math.PI; else theta = 2/3 * Math.PI; } else { if ( (ydiff < 0) && (xdiff <= 0 )) // quadrant 2 theta = -phi ; else if ( (ydiff > 0) && ( xdiff < 0 ) ) // quadrant 3 theta = 1/2 * Math.PI + phi; else if ( (ydiff > 0) && ( xdiff > 0 ) ) // quadrant 4 theta = -( 2 * Math.PI - phi ); else if ( (ydiff < 0) && ( xdiff >= 0 ) ) // quadrant 1 theta = -phi; } g.setColor( myColorScheme.getOverlayGraphEdgeColor() ); g.translate( x1, y1 ); g.rotate( theta ); // get the actual scaling factor used in visualization viewer. // assuming scaleX = scaleY double scaler = myGraphUI.getVV().getScaleX(); double scaledSrcRad = srcRadius * scaler; double scaledDestRad = destRadius * scaler; int endX = (int)(full_length - scaledDestRad); int [] xCoords = { endX - 7, endX -7, endX}; int [] yCoords = { 5, -5, 0}; if ( scaler > 0.3 ) g.setStroke( new BasicStroke(2)); else g.setStroke( new BasicStroke( 1 )); g.drawLine((int)scaledSrcRad, 0, endX, 0); g.fillPolygon( xCoords, yCoords, 3); g.setTransform( oldTransform ); g.setStroke( oldStroke ); } } protected HashSet myNodes = null; // set of nodes in the overlay graph protected HashSet myIndexNodes = null; // keeps track of nodes that have been added via addNodes protected Hashtable myEdges = null; // set of edges in the overlay graph protected DirectedSparseGraph parentGraph = null; protected SwoopModel myModel = null; protected OntologyWithClassHierarchyGraph myGraphUI = null; protected GraphColorScheme myColorScheme = null; protected Hashtable myCompleteRelations = null; public OverlayGraph( DirectedSparseGraph graph, SwoopModel model, OntologyWithClassHierarchyGraph ui ) { this.parentGraph = graph; this.myModel = model; this.myGraphUI = ui; this.myColorScheme = ui.getColorScheme(); init(); } /* * Iterating through all ontology vertices and bulid relations over the classes * in these ontologies. Called in constructor of OntologyWithClassHierarchyGraph */ public void precomputeAllRelations() { try { Set vertices = myGraphUI.getVisualGraph().getVertices(); for (Iterator it = vertices.iterator(); it.hasNext();) { SwoopOntologyVertex v = (SwoopOntologyVertex) it.next(); OntologyGraphNode ontNode = (OntologyGraphNode) v.getUserDatum(OntologyWithClassHierarchyGraph.DATA); // myModel.setSelectedOntology(ontNode.getOntology()); ClassTreeNode rootNode = ontNode.getTreeNode(); // root is OWL:Thing traverseAndPrebuild(rootNode); } } catch (Exception e) { e.printStackTrace(); } } /* * Traverses the tree and build relation for each node in the class tree */ private void traverseAndPrebuild( ClassTreeNode parentNode ) { Vector children = parentNode.getChildren(); for ( Iterator iter = children.iterator(); iter.hasNext(); ) { ClassTreeNode node = (ClassTreeNode)iter.next(); // get a child precomputeEdges( node ); // precompute its edges traverseAndPrebuild( node ); // now do its children } } /* * Given a class node, find all the relations it has to other classes, * store these relations, and set the node to 'has relations'. */ private void precomputeEdges( ClassTreeNode node ) { try { //System.out.println("precomputing for " + node.getURI() ); if ( node.getOWLClass() == null ) return; Set relatedClasses = findRelatedClasses(node.getOWLClass()); //System.out.println(" - has " + relatedClasses.size() + " many related classes: "); //for (Iterator it = relatedClasses.iterator(); it.hasNext(); ) // System.out.println( " ++ " + ((ClassTreeNode)it.next()).getURI() ); if ( relatedClasses.size() > 0 ) { myCompleteRelations.put( node, relatedClasses ); node.sethasRelations( true ); } } catch (Exception e) { e.printStackTrace(); } } private void init() { this.myNodes = new HashSet( 100 ); this.myIndexNodes = new HashSet( 100 ); this.myEdges = new Hashtable( 500 ); // indexed by source node, managed by a linked list this.myCompleteRelations = new Hashtable( 500 ); } /* * clear nodes and edges of the overlaygraph * clear the overlay mark on overlaied nodes */ public void clear() { for ( Iterator it = myNodes.iterator(); it.hasNext(); ) ((ClassTreeNode)it.next()).setIsOverlayed( false ); this.myNodes = new HashSet( 100 ); this.myIndexNodes = new HashSet( 100 ); this.myEdges = new Hashtable( 500 ); // indexed by source node, managed by a linked list } public void addNode( ClassTreeNode node ) { // check to see if it has been passed in as an argument to this method boolean isInserted = myIndexNodes.add(node); // if not, we insert it to myNodes, and grow edges out of it if ( isInserted ) { myNodes.add( node ); addEdges( node ); } } private void addEdges( ClassTreeNode node ) { try { node.setIsOverlayed( true ); //myModel.setSelectedOntology( node.getOntologyNode().getOntology() ); Set relatedClasses = (Set)myCompleteRelations.get( node ); // get from precomputed relations if ( relatedClasses == null) return; for ( Iterator it = relatedClasses.iterator(); it.hasNext(); ) { Object obj = it.next(); OWLClass cls = (OWLClass)obj; //System.out.println( cls.getURI().toString() ); } Set parentVertices = parentGraph.getVertices(); // walk through all ontologies to see if it contains any of the related classes // once found, put them into the 'myNodes' set // note that duplicate circles will be entered in duplications for (Iterator iter = parentVertices.iterator(); iter.hasNext(); ) { SwoopOntologyVertex vertex = (SwoopOntologyVertex)iter.next(); Object obj = vertex.getUserDatum( OntologyWithClassHierarchyGraph.DATA ); //System.out.println( obj.getClass().getName() ); OntologyGraphNode ontoNode = (OntologyGraphNode)obj; for (Iterator it = relatedClasses.iterator(); it.hasNext(); ) { OWLClass concept = (OWLClass)it.next(); Set classTreeNodes = ontoNode.findNodesBy( concept.getURI() ); if ( classTreeNodes != null ) { myNodes.addAll( classTreeNodes ); for (Iterator i = classTreeNodes.iterator(); i.hasNext(); ) { ClassTreeNode neighbor = (ClassTreeNode)i.next(); neighbor.setIsOverlayed( true ); //System.out.println("For " + myModel.shortForm( node.getURI()) + " - adding " + myModel.shortForm( neighbor.getURI() ) ); HashSet edgeSet = (HashSet)myEdges.get( node ); if ( edgeSet == null ) edgeSet = new HashSet(); edgeSet.add( new OverlayEdge(node, neighbor) ); myEdges.put( node, edgeSet ); } } } } } catch (OWLException e) { e.printStackTrace(); } } // code lifted from org.mindswap.swoop.TermsDisplay /* Need to do 3 things. * - look into subclass/equivalent axioms of this class for restrictions (arrows pointing out) * - look into properties for domains/ranges that relate this class to another one (arrows pointing in/out) * - look into show ref to see if other classes relate to this class (arrows pointing in) * */ /* public Set findRefs( OWLEntity entity ) { try { Set claSet = new HashSet(); //Set propSet = new HashSet(); //Set indSet = new HashSet(); Set vertices = parentGraph.getVertices(); for ( Iterator iterator = vertices.iterator(); iterator.hasNext(); ) { SwoopOntologyVertex vertex = (SwoopOntologyVertex)iterator.next(); OntologyGraphNode node = (OntologyGraphNode)vertex.getUserDatum( OntologyWithClassHierarchyGraph.DATA ); OWLOntology ontology = node.getOntology(); Set references = OntologyHelper.entityUsage(ontology, entity); for (Iterator iter = references.iterator(); iter.hasNext(); ) { Object obj = iter.next(); if (obj instanceof OWLClass) claSet.add(obj); //else if (obj instanceof OWLProperty) propSet.add(obj); //else if (obj instanceof OWLIndividual) indSet.add(obj); } } for (Iterator it = claSet.iterator(); it.hasNext(); ) System.out.println( it.next() ); return claSet; } catch (OWLException e) { e.printStackTrace(); } return null; } */ // returns a set of OWL classes that is related to clazz via restrictions/property domains/ranges protected Set findRelatedClasses( OWLClass clazz ) { try { HashSet relatedClasses = new HashSet(); SwoopReasoner reasoner = myModel.getReasoner(); OWLClass owlThing = reasoner.getOntology().getOWLDataFactory().getOWLThing(); ClassByRestrictionFinder finder = new ClassByRestrictionFinder( myModel ); // walk the INTERSECTIONs equivalent to this class Iterator it = OWLDescriptionFinder.getIntersections(clazz, reasoner.getOntologies()).iterator(); while(it.hasNext()) { OWLAnd intersection = (OWLAnd) it.next(); intersection.accept( finder ); if ( finder.found() ) relatedClasses.addAll( finder.getResult() ); finder.reset(); } // walk the UNIONs equivalent to this class it = OWLDescriptionFinder.getUnions(clazz, reasoner.getOntologies()).iterator(); while(it.hasNext()) { OWLOr union = (OWLOr) it.next(); union.accept( finder ); if ( finder.found() ) relatedClasses.addAll( finder.getResult() ); finder.reset(); } // walk ENUMERATIONs of classes that are equivalent to this class it = OWLDescriptionFinder.getEnumerations(clazz, reasoner.getOntologies()).iterator(); while(it.hasNext()) { OWLEnumeration oneOf = (OWLEnumeration) it.next(); oneOf.accept( finder ); if ( finder.found() ) relatedClasses.addAll( finder.getResult() ); finder.reset(); } // print EQUIVALENT classes Set eqs = OWLDescriptionFinder.getEquivalentClasses(clazz, reasoner.getOntologies()); it = eqs.iterator(); // removing the ones from above (and, or, oneof) and named classes while(it.hasNext()) { OWLDescription desc = (OWLDescription) it.next(); if(!(desc instanceof OWLRestriction)) it.remove(); } it = eqs.iterator(); while (it.hasNext()) { OWLDescription eq = (OWLDescription)it.next(); eq.accept( finder ); if ( finder.found() ) relatedClasses.addAll( finder.getResult() ); finder.reset(); } // SUBCLASS OF // acquiring all non-inferred super classes (named or anon) Set supers = OWLDescriptionFinder.getSuperClasses(clazz, reasoner.getOntologies()); Set ontos = reasoner.getOntologies(); //System.out.println( " SUPER SET = " + supers.size() ); if(reasoner.isConsistent(clazz)) { // remove all the named classes it = supers.iterator(); while(it.hasNext()) if(it.next() instanceof OWLClass) it.remove(); // remove owl:Thing from the superclass set it = supers.iterator(); while(it.hasNext()) { Object o = it.next(); if(o instanceof Set && ((Set)o).contains(owlThing)) it.remove(); } } for (it = supers.iterator(); it.hasNext(); ) { Object obj = (Object)it.next(); // if there is more than one element for this line // we only print the first one. rest are either // equivalent classes (or properties) if(obj instanceof Collection) obj = ((Collection)obj).iterator().next(); OWLDescription desc = (OWLDescription)obj; desc.accept( finder ); if ( finder.found() ) relatedClasses.addAll( finder.getResult() ); finder.reset(); } return relatedClasses; } catch ( OWLException e) { e.printStackTrace(); } return null; } public void paint( Graphics g ) { Graphics2D g2d = (Graphics2D)g; Set keys = myEdges.keySet(); for ( Iterator it = keys.iterator(); it.hasNext(); ) { ClassTreeNode node = (ClassTreeNode)it.next(); HashSet edges = (HashSet)myEdges.get( node ); for (Iterator iter = edges.iterator(); iter.hasNext(); ) { OverlayEdge edge = (OverlayEdge)iter.next(); edge.paint( g2d ); } } } // whether this Paintable uses its own transformation. (no) public boolean useTransform() { return false; } }