diff visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java @ 4512:015fb895586b

Moved visualizer to new directory.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 07 Feb 2012 22:41:09 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Tue Feb 07 22:41:09 2012 +0100
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.hierarchicallayout;
+
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Graph<N, E> {
+
+    private HashMap<Object, Node<N, E>> nodes;
+    private HashMap<Object, Edge<N, E>> edges;
+    private List<Node<N, E>> nodeList;
+
+    public Graph() {
+        nodes = new HashMap<>();
+        edges = new HashMap<>();
+        nodeList = new ArrayList<>();
+    }
+
+    public Node<N, E> createNode(N data, Object key) {
+        Node<N, E> n = new Node<>(this, data);
+        assert key == null || !nodes.containsKey(key);
+        if (key != null) {
+            nodes.put(key, n);
+        }
+        nodeList.add(n);
+        return n;
+    }
+
+    public Edge<N, E> createEdge(Node<N, E> source, Node<N, E> dest, E data, Object key) {
+        Edge<N, E> e = new Edge<>(this, source, dest, data);
+        source.addOutEdge(e);
+        dest.addInEdge(e);
+        if (key != null) {
+            edges.put(key, e);
+        }
+        return e;
+    }
+
+    public Node<N, E> getNode(Object key) {
+        return nodes.get(key);
+    }
+
+    public Edge<N, E> getEdge(Object key) {
+        return edges.get(key);
+    }
+
+    public Collection<Edge<N, E>> getEdges() {
+        return Collections.unmodifiableCollection(edges.values());
+    }
+
+    public Collection<Node<N, E>> getNodes() {
+        return Collections.unmodifiableList(nodeList);
+    }
+
+    public void removeEdge(Edge<N, E> e, Object key) {
+        assert key == null || edges.containsKey(key);
+        if (key != null) {
+            edges.remove(key);
+        }
+        e.getSource().removeOutEdge(e);
+        e.getDest().removeInEdge(e);
+    }
+
+    public class DFSTraversalVisitor {
+
+        public void visitNode(Node<N, E> n) {
+        }
+
+        public boolean visitEdge(Edge<N, E> e, boolean backEdge) {
+            return true;
+        }
+    }
+
+    public class BFSTraversalVisitor {
+
+        public void visitNode(Node<N, E> n, int depth) {
+        }
+    }
+
+    public List<Node<N, E>> getNodesWithInDegree(int x) {
+        return getNodesWithInDegree(x, true);
+    }
+
+    public List<Node<N, E>> getNodesWithInDegree(int x, boolean countSelfLoops) {
+
+        List<Node<N, E>> result = new ArrayList<>();
+        for (Node<N, E> n : getNodes()) {
+            if (n.getInDegree(countSelfLoops) == x) {
+                result.add(n);
+            }
+        }
+
+        return result;
+
+    }
+
+    private void markReachable(Node<N, E> startingNode) {
+        ArrayList<Node<N, E>> arr = new ArrayList<>();
+        arr.add(startingNode);
+        for (Node<N, E> n : getNodes()) {
+            n.setReachable(false);
+        }
+        traverseDFS(arr, new DFSTraversalVisitor() {
+
+            @Override
+            public void visitNode(Node<N, E> n) {
+                n.setReachable(true);
+            }
+        });
+    }
+
+    public void traverseBFS(Node<N, E> startingNode, BFSTraversalVisitor tv, boolean longestPath) {
+
+        if (longestPath) {
+            markReachable(startingNode);
+        }
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        Queue<Node<N, E>> queue = new LinkedList<>();
+        queue.add(startingNode);
+        startingNode.setVisited(true);
+        int layer = 0;
+        Node<N, E> lastOfLayer = startingNode;
+        Node<N, E> lastAdded = null;
+
+        while (!queue.isEmpty()) {
+
+            Node<N, E> current = queue.poll();
+            tv.visitNode(current, layer);
+            current.setActive(false);
+
+
+            for (Edge<N, E> e : current.getOutEdges()) {
+                if (!e.getDest().isVisited()) {
+
+                    boolean allow = true;
+                    if (longestPath) {
+                        for (Node<N, E> pred : e.getDest().getPredecessors()) {
+                            if ((!pred.isVisited() || pred.isActive()) && pred.isReachable()) {
+                                allow = false;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (allow) {
+                        queue.offer(e.getDest());
+                        lastAdded = e.getDest();
+                        e.getDest().setVisited(true);
+                        e.getDest().setActive(true);
+                    }
+                }
+            }
+
+            if (current == lastOfLayer && !queue.isEmpty()) {
+                lastOfLayer = lastAdded;
+                layer++;
+            }
+        }
+    }
+
+    public void traverseDFS(DFSTraversalVisitor tv) {
+        traverseDFS(getNodes(), tv);
+    }
+
+    public void traverseDFS(Collection<Node<N, E>> startingNodes, DFSTraversalVisitor tv) {
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        boolean result = false;
+        for (Node<N, E> n : startingNodes) {
+            traverse(tv, n);
+        }
+    }
+
+    private void traverse(DFSTraversalVisitor tv, Node<N, E> n) {
+
+        if (!n.isVisited()) {
+            n.setVisited(true);
+            n.setActive(true);
+            tv.visitNode(n);
+
+            for (Edge<N, E> e : n.getOutEdges()) {
+
+                Node<N, E> next = e.getDest();
+                if (next.isActive()) {
+                    tv.visitEdge(e, true);
+                } else {
+                    if (tv.visitEdge(e, false)) {
+                        traverse(tv, next);
+                    }
+                }
+            }
+
+            n.setActive(false);
+        }
+
+    }
+
+    public boolean hasCycles() {
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        boolean result = false;
+        for (Node<N, E> n : getNodes()) {
+            result |= checkCycles(n);
+            if (result) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private boolean checkCycles(Node<N, E> n) {
+
+        if (n.isActive()) {
+            return true;
+        }
+
+        if (!n.isVisited()) {
+
+            n.setVisited(true);
+            n.setActive(true);
+
+            for (Node<N, E> succ : n.getSuccessors()) {
+                if (checkCycles(succ)) {
+                    return true;
+                }
+            }
+
+            n.setActive(false);
+
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+
+        StringBuilder s = new StringBuilder();
+        s.append("Nodes: ");
+        for (Node<N, E> n : getNodes()) {
+            s.append(n.toString());
+            s.append("\n");
+        }
+
+        s.append("Edges: ");
+
+        for (Edge<N, E> e : getEdges()) {
+            s.append(e.toString());
+            s.append("\n");
+        }
+
+        return s.toString();
+    }
+}