/* * 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.Collections; import java.util.Comparator; 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 DummyEdgeCreator { NodeList nodeList; EdgeList edgeList; DirectedGraph graph; List<Edge> edgesAdded; List<Node> candidateList; int targetNodeIndex; boolean cleanNextTime = false; /** * @param clean * next time */ public void visit(DirectedGraph g) { cleanNextTime = true; init(g); setDummyEdges(); } /** * @param graph */ private void init(DirectedGraph graph) { this.graph = graph; this.nodeList = graph.nodes; this.edgeList = graph.edges; edgesAdded = new ArrayList<Edge>(); } @SuppressWarnings("unchecked") protected void setDummyEdges() { Node targetNode = null; int nodeCount = nodeList.size(); //if node count is only one then we don't have to worry about whether // the nodes are connected if (nodeCount > 1) { for (Iterator<Node> iter = nodeList.iterator(); iter.hasNext();) { Node sourceNode = iter.next(); //we will need to set up a dummy relationship for any table not // in one already if (sourceNode.outgoing.size() == 0 && sourceNode.incoming.size() == 0) { targetNode = findTargetNode(sourceNode); Edge edge = newDummyEdge(targetNode, sourceNode); edgesAdded.add(edge); } } } } /** * creates a new dummy edge to be used in the graph */ @SuppressWarnings("unchecked") private Edge newDummyEdge(Node targetNode, Node sourceNode) { DummyEdgePart edgePart = new DummyEdgePart(); Edge edge = new Edge(edgePart, sourceNode, targetNode); edge.weight = 2; edgeList.add(edge); return edge; } /** * @return a suitable first table to relate to. Will only be called if there * are > 1 table */ @SuppressWarnings("unchecked") private Node findTargetNode(Node cantBeThis) { if (candidateList == null) { candidateList = new NodeList(); boolean relationshipFound = false; //first look for set of targets which are already in relationships for (Iterator<Node> iter = nodeList.iterator(); iter.hasNext();) { Node element = iter.next(); if ((element.incoming.size() + element.outgoing.size()) >= 1) { candidateList.add(element); relationshipFound = true; } } //if none found, then just use the existing set if (!relationshipFound) { candidateList = nodeList; } // sort the target set with those in fewest relationships coming // first else { Comparator<Node> comparator = new Comparator<Node>() { public int compare(Node t1, Node t2) { return t1.incoming.size() - (t2.incoming.size()); } }; try { Collections.sort(candidateList, comparator); } catch (Exception e) { e.printStackTrace(); } //System.out.println("Sorted set: " + candidateList); } } //handle situation where first table is the top of the set - we will // want the next one then Node toReturn = getNext(); if (toReturn == cantBeThis) { toReturn = getNext(); } return toReturn; } private Node getNext() { if (targetNodeIndex == candidateList.size() - 1) targetNodeIndex = 0; else targetNodeIndex++; return candidateList.get(targetNodeIndex); } protected void removeDummyEdges() { for (Iterator<Edge> iter = edgesAdded.iterator(); iter.hasNext();) { Edge edge = iter.next(); edgeList.remove(edge); } } }