/*
* Created on Jul 14, 2004
*/
package com.realpersist.gef.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.DirectedGraphLayout;
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 extends DirectedGraphLayout
{
NodeList nodeList;
EdgeList edgeList;
DirectedGraph graph;
List edgesAdded;
List 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();
}
protected void setDummyEdges()
{
Node targetNode = null;
int nodeCount = nodeList.size();
boolean addedEdge = false;
//if node count is only one then we don't have to worry about whether
// the nodes are connected
if (nodeCount > 1)
{
for (Iterator iter = nodeList.iterator(); iter.hasNext();)
{
Node sourceNode = (Node) 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
*/
private Edge newDummyEdge(Node targetNode, Node sourceNode)
{
boolean addedEdge;
DummyEdgePart edgePart = new DummyEdgePart();
Edge edge = new Edge(edgePart, sourceNode, targetNode);
edge.weight = 2;
edgeList.add(edge);
targetNode = sourceNode;
addedEdge = true;
return edge;
}
/**
* @return a suitable first table to relate to. Will only be called if there
* are > 1 table
*/
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 iter = nodeList.iterator(); iter.hasNext();)
{
Node element = (Node) 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 comparator = new Comparator()
{
public int compare(Object o1, Object o2)
{
Node t1 = (Node) o1;
Node t2 = (Node) o2;
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 (Node) candidateList.get(targetNodeIndex);
}
protected void removeDummyEdges()
{
for (Iterator iter = edgesAdded.iterator(); iter.hasNext();)
{
Edge edge = (Edge) iter.next();
edgeList.remove(edge);
}
}
}