1/* 2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24package com.sun.hotspot.igv.hierarchicallayout; 25 26import java.awt.Point; 27import java.awt.Rectangle; 28import java.util.HashMap; 29import java.util.List; 30import java.util.Set; 31import java.util.ArrayList; 32import java.util.HashSet; 33import java.util.TreeSet; 34import com.sun.hotspot.igv.layout.Cluster; 35import com.sun.hotspot.igv.layout.LayoutGraph; 36import com.sun.hotspot.igv.layout.LayoutManager; 37import com.sun.hotspot.igv.layout.Link; 38import com.sun.hotspot.igv.layout.Port; 39import com.sun.hotspot.igv.layout.Vertex; 40 41/** 42 * 43 * @author Thomas Wuerthinger 44 */ 45public class HierarchicalClusterLayoutManager implements LayoutManager { 46 47 private HierarchicalLayoutManager.Combine combine; 48 private LayoutManager subManager = new HierarchicalLayoutManager(combine); 49 private LayoutManager manager = new HierarchicalLayoutManager(combine); 50 private static final boolean TRACE = false; 51 52 public HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine combine) { 53 this.combine = combine; 54 } 55 56 public void doLayout(LayoutGraph graph) { 57 doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>()); 58 } 59 60 public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) { 61 doLayout(graph); 62 } 63 64 public void setSubManager(LayoutManager manager) { 65 this.subManager = manager; 66 } 67 68 public void setManager(LayoutManager manager) { 69 this.manager = manager; 70 } 71 72 public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) { 73 74 assert graph.verify(); 75 76 HashMap<Cluster, List<Vertex>> lists = new HashMap<Cluster, List<Vertex>>(); 77 HashMap<Cluster, List<Link>> listsConnection = new HashMap<Cluster, List<Link>>(); 78 HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>> clusterInputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>>(); 79 HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>>(); 80 81 HashMap<Cluster, ClusterNode> clusterNodes = new HashMap<Cluster, ClusterNode>(); 82 HashMap<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new HashMap<Cluster, Set<ClusterInputSlotNode>>(); 83 HashMap<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new HashMap<Cluster, Set<ClusterOutputSlotNode>>(); 84 Set<Link> clusterEdges = new HashSet<Link>(); 85 Set<Link> interClusterEdges = new HashSet<Link>(); 86 HashMap<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new HashMap<Link, ClusterOutgoingConnection>(); 87 HashMap<Link, InterClusterConnection> linkInterClusterConnection = new HashMap<Link, InterClusterConnection>(); 88 HashMap<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new HashMap<Link, ClusterIngoingConnection>(); 89 Set<ClusterNode> clusterNodeSet = new HashSet<ClusterNode>(); 90 91 Set<Cluster> cluster = graph.getClusters(); 92 int z = 0; 93 for (Cluster c : cluster) { 94 lists.put(c, new ArrayList<Vertex>()); 95 listsConnection.put(c, new ArrayList<Link>()); 96 clusterInputSlotHash.put(c, new HashMap<Port, ClusterInputSlotNode>()); 97 clusterOutputSlotHash.put(c, new HashMap<Port, ClusterOutputSlotNode>()); 98 clusterOutputSlotSet.put(c, new TreeSet<ClusterOutputSlotNode>()); 99 clusterInputSlotSet.put(c, new TreeSet<ClusterInputSlotNode>()); 100 ClusterNode cn = new ClusterNode(c, "" + z); 101 clusterNodes.put(c, cn); 102 clusterNodeSet.add(cn); 103 z++; 104 } 105 106 // Add cluster edges 107 for (Cluster c : cluster) { 108 109 ClusterNode start = clusterNodes.get(c); 110 111 for (Cluster succ : c.getSuccessors()) { 112 ClusterNode end = clusterNodes.get(succ); 113 if (end != null && start != end) { 114 ClusterEdge e = new ClusterEdge(start, end); 115 clusterEdges.add(e); 116 interClusterEdges.add(e); 117 } 118 } 119 } 120 121 for (Vertex v : graph.getVertices()) { 122 Cluster c = v.getCluster(); 123 assert c != null : "Cluster of vertex " + v + " is null!"; 124 clusterNodes.get(c).addSubNode(v); 125 } 126 127 for (Link l : graph.getLinks()) { 128 129 Port fromPort = l.getFrom(); 130 Port toPort = l.getTo(); 131 Vertex fromVertex = fromPort.getVertex(); 132 Vertex toVertex = toPort.getVertex(); 133 Cluster fromCluster = fromVertex.getCluster(); 134 Cluster toCluster = toVertex.getCluster(); 135 136 Port samePort = null; 137 if (combine == HierarchicalLayoutManager.Combine.SAME_INPUTS) { 138 samePort = toPort; 139 } else if (combine == HierarchicalLayoutManager.Combine.SAME_OUTPUTS) { 140 samePort = fromPort; 141 } 142 143 assert listsConnection.containsKey(fromCluster); 144 assert listsConnection.containsKey(toCluster); 145 146 if (fromCluster == toCluster) { 147 listsConnection.get(fromCluster).add(l); 148 clusterNodes.get(fromCluster).addSubEdge(l); 149 } else { 150 ClusterInputSlotNode inputSlotNode = null; 151 ClusterOutputSlotNode outputSlotNode = null; 152 153 if (samePort != null) { 154 outputSlotNode = clusterOutputSlotHash.get(fromCluster).get(samePort); 155 inputSlotNode = clusterInputSlotHash.get(toCluster).get(samePort); 156 } 157 158 if (outputSlotNode == null) { 159 outputSlotNode = new ClusterOutputSlotNode(clusterNodes.get(fromCluster), "Out " + fromCluster.toString() + " " + samePort.toString()); 160 clusterOutputSlotSet.get(fromCluster).add(outputSlotNode); 161 ClusterOutgoingConnection conn = new ClusterOutgoingConnection(outputSlotNode, l); 162 outputSlotNode.setOutgoingConnection(conn); 163 clusterNodes.get(fromCluster).addSubEdge(conn); 164 if (samePort != null) { 165 clusterOutputSlotHash.get(fromCluster).put(samePort, outputSlotNode); 166 } 167 168 linkClusterOutgoingConnection.put(l, conn); 169 } else { 170 linkClusterOutgoingConnection.put(l, outputSlotNode.getOutgoingConnection()); 171 } 172 173 if (inputSlotNode == null) { 174 inputSlotNode = new ClusterInputSlotNode(clusterNodes.get(toCluster), "In " + toCluster.toString() + " " + samePort.toString()); 175 clusterInputSlotSet.get(toCluster).add(inputSlotNode); 176 } 177 178 ClusterIngoingConnection conn = new ClusterIngoingConnection(inputSlotNode, l); 179 inputSlotNode.setIngoingConnection(conn); 180 clusterNodes.get(toCluster).addSubEdge(conn); 181 if (samePort != null) { 182 clusterInputSlotHash.get(toCluster).put(samePort, inputSlotNode); 183 } 184 185 linkClusterIngoingConnection.put(l, conn); 186 187 188 InterClusterConnection interConn = new InterClusterConnection(outputSlotNode, inputSlotNode); 189 linkInterClusterConnection.put(l, interConn); 190 clusterEdges.add(interConn); 191 } 192 } 193 194 Timing t = null; 195 196 if (TRACE) { 197 new Timing("Child timing"); 198 t.start(); 199 } 200 201 for (Cluster c : cluster) { 202 ClusterNode n = clusterNodes.get(c); 203 subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), new HashSet<Link>()); 204 n.updateSize(); 205 } 206 207 Set<Vertex> roots = new LayoutGraph(interClusterEdges).findRootVertices(); 208 for (Vertex v : roots) { 209 assert v instanceof ClusterNode; 210 ((ClusterNode) v).setRoot(true); 211 } 212 213 manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), interClusterEdges); 214 215 for (Cluster c : cluster) { 216 ClusterNode n = clusterNodes.get(c); 217 c.setBounds(new Rectangle(n.getPosition(), n.getSize())); 218 } 219 220 // TODO: handle case where blocks are not fully connected 221 222 if (TRACE) { 223 t.stop(); 224 t.print(); 225 } 226 227 for (Link l : graph.getLinks()) { 228 229 if (linkInterClusterConnection.containsKey(l)) { 230 ClusterOutgoingConnection conn1 = linkClusterOutgoingConnection.get(l); 231 InterClusterConnection conn2 = linkInterClusterConnection.get(l); 232 ClusterIngoingConnection conn3 = linkClusterIngoingConnection.get(l); 233 234 assert conn1 != null; 235 assert conn2 != null; 236 assert conn3 != null; 237 238 List<Point> points = new ArrayList<Point>(); 239 240 points.addAll(conn1.getControlPoints()); 241 points.addAll(conn2.getControlPoints()); 242 points.addAll(conn3.getControlPoints()); 243 244 l.setControlPoints(points); 245 } 246 } 247 } 248 249 public void doRouting(LayoutGraph graph) { 250 } 251} 252