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 */ 24 package com.sun.hotspot.igv.graph; 25 26 import com.sun.hotspot.igv.data.InputBlock; 27 import com.sun.hotspot.igv.data.InputEdge; 28 import com.sun.hotspot.igv.data.InputGraph; 29 import com.sun.hotspot.igv.data.InputNode; 30 import com.sun.hotspot.igv.data.Properties; 31 import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; 32 import java.awt.Font; 33 import java.util.*; 34 35 /** 36 * 37 * @author Thomas Wuerthinger 38 */ 39 public class Diagram { 40 41 private List<Figure> figures; 42 private Map<InputBlock, Block> blocks; 43 private InputGraph graph; 44 private int curId; 45 private String nodeText; 46 private final Font font; 47 private final Font slotFont; 48 private final Font boldFont; 49 getFont()50 public Font getFont() { 51 return font; 52 } 53 getSlotFont()54 public Font getSlotFont() { 55 return slotFont; 56 } 57 getBoldFont()58 public Font getBoldFont() { 59 return boldFont; 60 } 61 Diagram()62 private Diagram() { 63 figures = new ArrayList<>(); 64 blocks = new LinkedHashMap<>(8); 65 this.nodeText = ""; 66 this.font = new Font("Arial", Font.PLAIN, 12); 67 this.slotFont = new Font("Arial", Font.PLAIN, 10); 68 this.boldFont = this.font.deriveFont(Font.BOLD); 69 } 70 getBlock(InputBlock b)71 public Block getBlock(InputBlock b) { 72 assert blocks.containsKey(b); 73 return blocks.get(b); 74 } 75 getNodeText()76 public String getNodeText() { 77 return nodeText; 78 } 79 updateBlocks()80 public void updateBlocks() { 81 blocks.clear(); 82 for (InputBlock b : graph.getBlocks()) { 83 Block curBlock = new Block(b, this); 84 blocks.put(b, curBlock); 85 } 86 } 87 getNext()88 public Diagram getNext() { 89 return Diagram.createDiagram(graph.getNext(), nodeText); 90 } 91 getBlocks()92 public Collection<Block> getBlocks() { 93 return Collections.unmodifiableCollection(blocks.values()); 94 } 95 getPrev()96 public Diagram getPrev() { 97 return Diagram.createDiagram(graph.getPrev(), nodeText); 98 } 99 getFigures()100 public List<Figure> getFigures() { 101 return Collections.unmodifiableList(figures); 102 } 103 createFigure()104 public Figure createFigure() { 105 Figure f = new Figure(this, curId); 106 curId++; 107 this.figures.add(f); 108 return f; 109 } 110 createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type)111 public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) { 112 assert inputSlot.getFigure().getDiagram() == this; 113 assert outputSlot.getFigure().getDiagram() == this; 114 return new Connection(inputSlot, outputSlot, label, type); 115 } 116 calcSourceToFigureRelation()117 public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() { 118 Map<InputNode, Set<Figure>> map = new HashMap<>(); 119 120 for(InputNode node : this.getGraph().getNodes()) { 121 map.put(node, new HashSet<Figure>()); 122 } 123 124 for(Figure f : this.getFigures()) { 125 for(InputNode node : f.getSource().getSourceNodes()) { 126 map.get(node).add(f); 127 } 128 } 129 130 return map; 131 } 132 createDiagram(InputGraph graph, String nodeText)133 public static Diagram createDiagram(InputGraph graph, String nodeText) { 134 if (graph == null) { 135 return null; 136 } 137 138 Diagram d = new Diagram(); 139 d.graph = graph; 140 d.nodeText = nodeText; 141 142 d.updateBlocks(); 143 144 Collection<InputNode> nodes = graph.getNodes(); 145 Hashtable<Integer, Figure> figureHash = new Hashtable<>(); 146 for (InputNode n : nodes) { 147 Figure f = d.createFigure(); 148 f.getSource().addSourceNode(n); 149 f.getProperties().add(n.getProperties()); 150 f.setSubgraphs(n.getSubgraphs()); 151 figureHash.put(n.getId(), f); 152 } 153 154 for (InputEdge e : graph.getEdges()) { 155 156 int from = e.getFrom(); 157 int to = e.getTo(); 158 Figure fromFigure = figureHash.get(from); 159 Figure toFigure = figureHash.get(to); 160 161 if(fromFigure == null || toFigure == null) continue; 162 assert fromFigure != null && toFigure != null; 163 164 int fromIndex = e.getFromIndex(); 165 while (fromFigure.getOutputSlots().size() <= fromIndex) { 166 fromFigure.createOutputSlot(); 167 } 168 OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex); 169 170 int toIndex = e.getToIndex(); 171 while (toFigure.getInputSlots().size() <= toIndex) { 172 toFigure.createInputSlot(); 173 } 174 InputSlot inputSlot = toFigure.getInputSlots().get(toIndex); 175 176 Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType()); 177 178 if (e.getState() == InputEdge.State.NEW) { 179 c.setStyle(Connection.ConnectionStyle.BOLD); 180 } else if (e.getState() == InputEdge.State.DELETED) { 181 c.setStyle(Connection.ConnectionStyle.DASHED); 182 } 183 } 184 185 186 return d; 187 } 188 removeAllFigures(Set<Figure> figuresToRemove)189 public void removeAllFigures(Set<Figure> figuresToRemove) { 190 for (Figure f : figuresToRemove) { 191 freeFigure(f); 192 } 193 194 ArrayList<Figure> newFigures = new ArrayList<>(); 195 for (Figure f : this.figures) { 196 if (!figuresToRemove.contains(f)) { 197 newFigures.add(f); 198 } 199 } 200 figures = newFigures; 201 } 202 freeFigure(Figure succ)203 private void freeFigure(Figure succ) { 204 205 List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots()); 206 for (InputSlot s : inputSlots) { 207 succ.removeInputSlot(s); 208 } 209 210 List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots()); 211 for (OutputSlot s : outputSlots) { 212 succ.removeOutputSlot(s); 213 } 214 215 assert succ.getInputSlots().size() == 0; 216 assert succ.getOutputSlots().size() == 0; 217 assert succ.getPredecessors().size() == 0; 218 assert succ.getSuccessors().size() == 0; 219 220 } 221 removeFigure(Figure succ)222 public void removeFigure(Figure succ) { 223 224 assert this.figures.contains(succ); 225 freeFigure(succ); 226 this.figures.remove(succ); 227 } 228 getName()229 public String getName() { 230 return graph.getName(); 231 } 232 getGraph()233 public InputGraph getGraph() { 234 return graph; 235 } 236 getConnections()237 public Set<Connection> getConnections() { 238 239 Set<Connection> connections = new HashSet<>(); 240 for (Figure f : figures) { 241 242 for (InputSlot s : f.getInputSlots()) { 243 connections.addAll(s.getConnections()); 244 } 245 } 246 247 return connections; 248 } 249 getRootFigure()250 public Figure getRootFigure() { 251 Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(figures); 252 Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root")); 253 if (root == null) { 254 root = selector.selectSingle(new StringPropertyMatcher("name", "Start")); 255 } 256 if (root == null) { 257 List<Figure> rootFigures = getRootFigures(); 258 if (rootFigures.size() > 0) { 259 root = rootFigures.get(0); 260 } else if (figures.size() > 0) { 261 root = figures.get(0); 262 } 263 } 264 265 return root; 266 } 267 printStatistics()268 public void printStatistics() { 269 System.out.println("============================================================="); 270 System.out.println("Diagram statistics"); 271 272 List<Figure> tmpFigures = getFigures(); 273 Set<Connection> connections = getConnections(); 274 275 System.out.println("Number of figures: " + tmpFigures.size()); 276 System.out.println("Number of connections: " + connections.size()); 277 278 List<Figure> figuresSorted = new ArrayList<>(tmpFigures); 279 Collections.sort(figuresSorted, new Comparator<Figure>() { 280 281 @Override 282 public int compare(Figure a, Figure b) { 283 return b.getPredecessors().size() + b.getSuccessors().size() - a.getPredecessors().size() - a.getSuccessors().size(); 284 } 285 }); 286 287 final int COUNT = 10; 288 int z = 0; 289 for (Figure f : figuresSorted) { 290 291 z++; 292 int sum = f.getPredecessors().size() + f.getSuccessors().size(); 293 System.out.println("#" + z + ": " + f + ", predCount=" + f.getPredecessors().size() + " succCount=" + f.getSuccessors().size()); 294 if (sum < COUNT) { 295 break; 296 } 297 298 } 299 300 System.out.println("============================================================="); 301 } 302 getRootFigures()303 public List<Figure> getRootFigures() { 304 ArrayList<Figure> rootFigures = new ArrayList<>(); 305 for (Figure f : figures) { 306 if (f.getPredecessors().size() == 0) { 307 rootFigures.add(f); 308 } 309 } 310 return rootFigures; 311 } 312 } 313