/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on Jul 14, 2004
*/
package org.jkiss.dbeaver.ext.erd.layout.algorithm.direct;
import org.eclipse.draw2d.graph.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Creates dummy edges between nodes, to be used with NodeJoiningDirectedGraphLayout
*
* @author Serge Rider
*/
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 edgesAdded;
List<Node> encountered = new ArrayList<>();
List<Cluster> clusters = new ArrayList<>();
Cluster currentCluster = null;
public ClusterEdgeCreator() {
super();
}
public void visit(DirectedGraph graph) {
try {
this.graph = graph;
this.nodeList = graph.nodes;
this.edgeList = graph.edges;
//edgesAdded = new ArrayList();
//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);
// recursively add any other nodes reachable from it
int depth = INITIAL_RECURSION_DEPTH;
recursivelyAddToCluster(node, depth);
}
}
/*
for (Iterator<Cluster> iter = clusters.iterator(); iter.hasNext();) {
Cluster cluster = iter.next();
}
*/
coalesceRemainingClusters();
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) {
// do nothing
} 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);
recursivelyAddToCluster(incomingNode, depth);
}
}
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);
recursivelyAddToCluster(outgoingNode, depth);
}
}
}
}
/**
* creates a new dummy edge to be used in the graph
*/
private Edge newDummyEdge(Node sourceNode, Node targetNode) {
//boolean addedEdge;
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;
//addedEdge = true;
return edge;
}
/**
* Very thin wrapper around List
*/
private class Cluster {
List<Node> set = new ArrayList<>();
public String toString() {
return set.toString();
}
}
}