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