/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.hibernate.eclipse.graph.layout; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.graph.DirectedGraph; import org.eclipse.draw2d.graph.Edge; import org.eclipse.draw2d.graph.EdgeList; import org.eclipse.draw2d.graph.Node; import org.eclipse.draw2d.graph.NodeList; /** * Creates dummy edges between nodes, to be used with NodeJoiningDirectedGraphLayout * @author Phil Zoio */ public class ClusterEdgeCreator { //sets up maximum depth of recursion to set up initial cluster list private static final int INITIAL_RECURSION_DEPTH = 3; NodeList nodeList; EdgeList edgeList; DirectedGraph graph; List<Node> encountered = new ArrayList<Node>(); List<Cluster> clusters = new ArrayList<Cluster>(); Cluster currentCluster = null; /** * @param graph */ public ClusterEdgeCreator() { super(); } public void visit(DirectedGraph graph) { try { this.graph = graph; this.nodeList = graph.nodes; this.edgeList = graph.edges; //iterate through all of the nodes in the node list for (Iterator<?> iter = nodeList.iterator(); iter.hasNext();) { Node node = (Node)iter.next(); //check whether we have already come across this node if (!encountered.contains(node)) { //create a new cluster for this node currentCluster = new Cluster(); clusters.add(currentCluster); encountered.add(node); currentCluster.set.add(node); //System.out.println("Adding to NEW cluster: " + node + ", cluster: " + currentCluster); // recursively add any other nodes reachable from it int depth = INITIAL_RECURSION_DEPTH; recursivelyAddToCluster(node, depth); } else { //System.out.println("Already encountered: " + node); } } /*System.out.println("Clusters: "); for (Iterator<Cluster> iter = clusters.iterator(); iter.hasNext();) { Cluster cluster = iter.next(); System.out.println(cluster); }*/ coalesceRemainingClusters(); //System.out.println(""); joinClusters(); } catch (RuntimeException e) { e.printStackTrace(); throw e; } } /** * If recursion fails to join all the remaining */ private void coalesceRemainingClusters() { } /** * Joins the clusters together */ private void joinClusters() { if (clusters.size() > 1) { Node sourceNode = null; Node targetNode = null; //add an edge from each successive cluster to next for (Iterator<Cluster> iter = clusters.iterator(); iter.hasNext();) { Cluster cluster = iter.next(); if (sourceNode != null) { //use first node in set as target node targetNode = cluster.set.get(0); newDummyEdge(sourceNode, targetNode); } //set up source node for the next iteration using last node in // set sourceNode = cluster.set.get(cluster.set.size() - 1); } } } private void recursivelyAddToCluster(Node node, int depth) { if (depth > 3) return; else { depth++; EdgeList incoming = node.incoming; for (Iterator<?> iter = incoming.iterator(); iter.hasNext();) { Edge edge = (Edge)iter.next(); Node incomingNode = edge.source; if (!encountered.contains(incomingNode)) { encountered.add(incomingNode); currentCluster.set.add(incomingNode); //System.out.println("Adding to current cluster: " + incomingNode + ", cluster: " + currentCluster); recursivelyAddToCluster(incomingNode, depth); } else { //System.out.println("Already encountered: " + incomingNode); } } EdgeList outgoing = node.outgoing; for (Iterator<?> iter = outgoing.iterator(); iter.hasNext();) { Edge edge = (Edge) iter.next(); Node outgoingNode = edge.target; if (!encountered.contains(outgoingNode)) { encountered.add(outgoingNode); currentCluster.set.add(outgoingNode); //System.out.println("Adding to current cluster: " + outgoingNode + ", cluster: " + currentCluster); recursivelyAddToCluster(outgoingNode, depth); } else { //System.out.println("Already encountered: " + outgoingNode); } } } } /** * creates a new dummy edge to be used in the graph */ @SuppressWarnings("unchecked") private Edge newDummyEdge(Node sourceNode, Node targetNode) { DummyEdgePart edgePart = new DummyEdgePart(); Edge edge = new Edge(edgePart, sourceNode, targetNode); edge.weight = 2; //add the new edge to the edge list edgeList.add(edge); //targetNode = sourceNode; return edge; } /** * Very thin wrapper around List */ static private class Cluster { List<Node> set = new ArrayList<Node>(); public String toString() { return set.toString(); } } }