diff --git a/src/main/java/org/spideruci/analysis/trace/MethodTraceDirReader.java b/src/main/java/org/spideruci/analysis/trace/MethodTraceDirReader.java new file mode 100644 index 0000000..e6f4233 --- /dev/null +++ b/src/main/java/org/spideruci/analysis/trace/MethodTraceDirReader.java @@ -0,0 +1,101 @@ +package org.spideruci.analysis.trace; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.spideruci.analysis.trace.io.TraceReader; +import org.spideruci.cerebro.layout.model.DynamicFlowGraph; +import org.spideruci.cerebro.layout.model.FlowIdent; +import org.spideruci.cerebro.layout.model.SourceLineNode; + +public class MethodTraceDirReader extends TraceDirReader { + private static HashMap> methodMap = new HashMap<>(); + + public MethodTraceDirReader() { + // TODO Auto-generated constructor stub + } + + public static DynamicFlowGraph scanTraceFiles(File[] files, final String path) + throws IOException { + if(path == null) { + throw new RuntimeException("path is null ... fuck it!"); + } + + DynamicFlowGraph dynamicFlowGraph = new DynamicFlowGraph(); + for(File f : files) { + if(f == null || !f.isFile() || !f.getName().endsWith(".trc")) { + continue; + } + + String name = f.getName(); + System.out.println("Scanning " + name); + PrintStream jsonTraceStream = new PrintStream(path + name + ".json"); + jsonTraceStream.println("["); + + TraceReader traceReader = new TraceReader(f); + HashMap threadedPrevious = new HashMap<>(); + int count = 0; + String prevMethod = ""; + String prevClass = ""; + + while(true) { + TraceEvent event = traceReader.readNextExecutedEvent(); + if(event == null) { + break; + } + + if(event.getExecInsnType() != EventType.$line$) { + continue; + } + + String ownerClass = traceReader.getExecutedEventOwnerClass(event); + String ownerMethod = traceReader.getExecutedEventOwnerMethod(event); + int lineNumber = traceReader.getExecutedEventSourceLine(event); + String threadId = event.getExecThreadId(); + + SourceLineNode node = new SourceLineNode(ownerClass, ownerMethod, lineNumber); + + if(!ownerMethod.equals(prevMethod) && !ownerClass.equals(prevClass)){ + if(!methodMap.containsKey(node.methodName())){ + node = dynamicFlowGraph.addNode(node); + Map temp = new HashMap<>(); + temp.put(node.className(), node); + methodMap.put(node.methodName(), temp); + } + else{ + if(methodMap.get(node.methodName()).get(node.className()) != null) + node = methodMap.get(node.methodName()).get(node.className()); + else{ + node = dynamicFlowGraph.addNode(node); + methodMap.get(node.methodName()).put(node.className(), node); + } + } + + + spitJsonTrace(jsonTraceStream, node.id()); + count += 1; + SourceLineNode previous = threadedPrevious.get(threadId); + if(previous != null) { + dynamicFlowGraph.addEdge(previous, node); + } + + threadedPrevious.put(threadId, node); + } + prevMethod = ownerMethod; + prevClass = ownerClass; + } + + jsonTraceStream.println("0]"); + FlowIdent ident = new FlowIdent(name, count); + dynamicFlowGraph.addFlows(ident); + } + + return dynamicFlowGraph; + } + +} diff --git a/src/main/java/org/spideruci/analysis/trace/TraceDirReader.java b/src/main/java/org/spideruci/analysis/trace/TraceDirReader.java index 3105ed8..45ef6e5 100644 --- a/src/main/java/org/spideruci/analysis/trace/TraceDirReader.java +++ b/src/main/java/org/spideruci/analysis/trace/TraceDirReader.java @@ -84,7 +84,7 @@ public static DynamicFlowGraph scanTraceFiles(File[] files, final String path) node = dynamicFlowGraph.addNode(node); - spitJsonTrace(jsonTraceStream, node.id); + spitJsonTrace(jsonTraceStream, node.id()); count += 1; SourceLineNode previous = threadedPrevious.get(threadId); if(previous != null) { @@ -102,7 +102,7 @@ public static DynamicFlowGraph scanTraceFiles(File[] files, final String path) return dynamicFlowGraph; } - private static void spitJsonTrace(PrintStream out, int nodeId) { + protected static void spitJsonTrace(PrintStream out, int nodeId) { out.print(nodeId + ",\n"); } diff --git a/src/main/java/org/spideruci/cerebro/Cerebro.java b/src/main/java/org/spideruci/cerebro/Cerebro.java index 05c0dda..a60eb55 100644 --- a/src/main/java/org/spideruci/cerebro/Cerebro.java +++ b/src/main/java/org/spideruci/cerebro/Cerebro.java @@ -7,7 +7,7 @@ import java.io.IOException; import org.graphstream.ui.layout.springbox.BarnesHutLayout; - +import org.spideruci.analysis.trace.MethodTraceDirReader; import org.spideruci.analysis.trace.TraceDirReader; import org.spideruci.cerebro.community.JungCommunityComputer; import org.spideruci.cerebro.layout.model.DynamicFlowGraph; @@ -67,6 +67,7 @@ public static DynamicFlowGraph getDynamicFlowGraph(String[] args) throws IOExcep String tracePath = args[0]; File[] files = TraceDirReader.getFiles(args[0]); dynamicFlowGraph = TraceDirReader.scanTraceFiles(files, tracePath); +// dynamicFlowGraph = MethodTraceDirReader.scanTraceFiles(files, tracePath); } return dynamicFlowGraph; diff --git a/src/main/java/org/spideruci/cerebro/layout/Commands.java b/src/main/java/org/spideruci/cerebro/layout/Commands.java index 10245c1..feeef78 100644 --- a/src/main/java/org/spideruci/cerebro/layout/Commands.java +++ b/src/main/java/org/spideruci/cerebro/layout/Commands.java @@ -16,6 +16,7 @@ public enum Commands { COLOR_BY_METHOD, COLOR_BY_CLASS, REMOVE_COLOR, + FIND_START_NODE, DONE, HELP; @@ -80,6 +81,9 @@ public static boolean handleInput(DynamicDisplay display, case COLOR_BY_CLASS: display.colorNodesByClass(); break; + case FIND_START_NODE: + display.setStartNode(); + break; case HELP: System.out.println(Commands.mainMenu); break; diff --git a/src/main/java/org/spideruci/cerebro/layout/DynamicDisplay.java b/src/main/java/org/spideruci/cerebro/layout/DynamicDisplay.java index 4199813..2c32d8a 100644 --- a/src/main/java/org/spideruci/cerebro/layout/DynamicDisplay.java +++ b/src/main/java/org/spideruci/cerebro/layout/DynamicDisplay.java @@ -29,326 +29,333 @@ public class DynamicDisplay { - private Graph graph; - public Viewer viewer; - private GraphicGraph ggraph; - SortedSet buffer; - DynamicFlowGraph displayedGraph; - - LinLog layout; - - private static int uniqId = 0; - public static final String DEFAULT_TITLE = "Cerebro"; - private static final int BUFFER_LIMIT = 300; - - public static DynamicDisplay init(String title, DynamicFlowGraph displayedGraph) { - System.setProperty("org.graphstream.ui.renderer", - "org.graphstream.ui.j2dviewer.J2DGraphRenderer"); - DynamicDisplay display = new DynamicDisplay(title, displayedGraph); - - display.setup(); - - display.launchDisplay(); - return display; - } - - private DynamicDisplay(String title, DynamicFlowGraph displayedGraph) { - graph = new MultiGraph(title); - buffer = Collections.synchronizedSortedSet(new TreeSet()); - this.displayedGraph = displayedGraph; - } - - private void setup() { - this.graph.setStrict(false); - this.graph.setAutoCreate(true); - File file = new File("css/stylesheet.css"); - String url = "url(file://" + file.getAbsolutePath() + ")"; - this.graph.addAttribute("ui.stylesheet", url); - this.graph.addAttribute("layout.quality", 4); - this.buffer.clear(); - } - - private void launchDisplay() { - this.viewer = this.graph.display(); - this.viewer.disableAutoLayout(); - - this.ggraph = this.viewer.getGraphicGraph(); - - View view = this.viewer.getDefaultView(); - - ViewerPipe fromViewer = this.viewer.newViewerPipe(); - ViewerEventListener viewerListener = - new ViewerEventListener(fromViewer, this.displayedGraph); - view.setMouseManager(viewerListener); - view.addMouseWheelListener(viewerListener); - fromViewer.addViewerListener(viewerListener); - fromViewer.addSink(this.graph); - } - - public void clear() { - this.graph.clear(); - } - - public synchronized void showDependence(int from, int to) { - showDependence(String.valueOf(from), String.valueOf(to), Double.NaN); - } - - public synchronized void showDependence(int from, int to, double weight) { - showDependence(String.valueOf(from), String.valueOf(to), weight); - } - - public void showDependence(String from, String to) { - showDependence(from, to, Double.NaN); - } - - public synchronized void showDependence(String from, String to, double weight) { - showDependence(from, Double.NaN, Double.NaN, to, Double.NaN, Double.NaN, weight); - } - - public synchronized void showDependence(int from, double fX, double fY, - int to, double tX, double tY, - double weight) { - showDependence(String.valueOf(from), fX, fY, String.valueOf(to), tX, tY, weight); - } - - public synchronized void showDependence(String from, double fX, double fY, - String to, double tX, double tY, - double weight) { - showNode(from, fX, fY); - showNode(to, tX, tY); - int id = uniqId++; - - try { - Node fromNode = graph.getNode(from); - if(fromNode == null || !fromNode.hasEdgeToward(to)) { - Edge edge = graph.addEdge(String.valueOf(id), from, to, true); - edge.addAttribute("ui.hide"); - - final String style = - String.format("fill-color: rgba(150,150,150,50);size: %spx;", - Double.isNaN(weight) ? 5 : plateau(weight)); - edge.addAttribute("ui.style", style); - } - } catch (IdAlreadyInUseException e) { } - } - - private double plateau(double value) { - Preconditions.checkArgument(!Double.isNaN(value)); - return 1.2*(1 + Math.log(value)); - } - - private void showNode(String nodeId, double x, double y) { - try { - Node node = graph.addNode(nodeId); - if(!Double.isNaN(x)) { - node.addAttribute("x", x); - } - - if(!Double.isNaN(y)) { - node.addAttribute("y", y); - } - - } catch(IdAlreadyInUseException nodeInUse) { } - } - - private void removeNode(String nodeId) { - try { - graph.removeNode(nodeId); - } catch(ElementNotFoundException nodeNotFound) { - // Do nothing for now. - } - } - - @SuppressWarnings("unused") - private synchronized void bufferNodes(int nodeId1, int nodeId2) { - buffer.add(nodeId1); - buffer.add(nodeId2); - - while(buffer.size() > BUFFER_LIMIT) { - int oldestNode = buffer.first(); - buffer.remove(oldestNode); - removeNode(String.valueOf(oldestNode)); - } - - for(Node node : graph.getEachNode()) { - if(node.getEdgeSet().size() == 0) { - buffer.remove(Integer.parseInt(node.getId())); - graph.removeNode(node); - } - } - } - - public static void play() throws IOException { } - - public void spitImage(int id) throws IOException { - FileSinkImages pic = new FileSinkImages(OutputType.PNG, Resolutions.VGA); - - pic.setLayoutPolicy(LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE); - pic.writeAll(this.graph, this.graph.getId() + id + ".png"); - } - - public void spitImage(String id) throws IOException { - FileSinkImages pic = new FileSinkImages(OutputType.PNG, Resolutions.VGA); - - pic.setLayoutPolicy(LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE); - pic.writeAll(this.graph, id + ".png"); - } - - public void weighEdges() { - double maxCount = displayedGraph.maxEdgeCount() + 1.0; - for(Edge edge : graph.getEachEdge()) { - Node from = edge.getSourceNode(); - Node to = edge.getTargetNode(); - int fromId = Integer.parseInt(from.toString()); - int toId = Integer.parseInt(to.toString()); - int count = displayedGraph.getEdgeCount(fromId, toId); - double weight = (maxCount - count)/maxCount; - edge.addAttribute("layout.weight", weight); - } - } - - public void colorNodes() { - int clusterCount = displayedGraph.getClusterCount(); - String[] palette = ColorPalette.generatePalette(clusterCount); - - for(Node node : graph.getEachNode()) { - int nodeId = Integer.valueOf(node.getId()); - SourceLineNode dynamicNode = displayedGraph.getNode(nodeId); - int colorIndex = dynamicNode.colorGroup; - if(colorIndex <= -1) { - continue; - } - - colorNode(palette, colorIndex, node); - } - } - - public void colorNodesByClass() { - int classCodeCount = displayedGraph.classCodeCount(); - String[] palette = ColorPalette.generatePalette(classCodeCount); - - for(Node node : graph.getEachNode()) { - int nodeId = Integer.valueOf(node.getId()); - int colorIndex = displayedGraph.getNodeClassCode(nodeId); - - if(colorIndex <= -1) { - continue; - } - - colorNode(palette, colorIndex, node); - } - } - - public void colorNodesByMethod() { - int methodCodeCount = displayedGraph.methodCodeCount(); - String[] palette = ColorPalette.generatePalette(methodCodeCount); - - for(Node node : graph.getEachNode()) { - int nodeId = Integer.valueOf(node.getId()); - int colorIndex = displayedGraph.getNodeMethodCode(nodeId); - - if(colorIndex <= -1) { - continue; - } - - colorNode(palette, colorIndex, node); - } - } - - private void colorNode(String[] palette, int colorIndex, Node node) { - Preconditions.checkNotNull(palette); - Preconditions.checkElementIndex(colorIndex, palette.length); - String color = palette[colorIndex % palette.length]; - String colorStyle = "fill-color: " + color + ";"; - node.setAttribute("ui.style", colorStyle); - } - - public void decolorNodes() { - for(Node node : graph.getEachNode()) { - node.setAttribute("ui.style", "fill-color:lightyellow;"); - } - } - - private int nodeSize = 4; - - public void expandNodes() { - if(nodeSize < 20) { - nodeSize += 1; - } - - for(Node node : graph.getEachNode()) { - node.setAttribute("ui.style", - String.format("size: %spx;", nodeSize)); - } - } - - public void shrinkNodes() { - if(nodeSize > 4) { - nodeSize -= 1; - } - - for(Node node : graph.getEachNode()) { - node.setAttribute("ui.style", - String.format("size: %spx;", nodeSize)); - } - } - - public void showEdges() { - for(Edge edge : graph.getEachEdge()) { - edge.removeAttribute("ui.hide"); - } - } - - public void hideEdges() { - for(Edge edge : graph.getEachEdge()) { - edge.addAttribute("ui.hide"); - } - } - - public void pinNodesOnDynamicFlowGraph() { - for(Node node : ggraph.getEachNode()) { - int nodeId = Integer.valueOf(node.getId()); - SourceLineNode lineNode = displayedGraph.getNode(nodeId); -// int colorGroup = displayedGraph.getNodeClassCode(nodeId); -// lineNode.initColorGroup(colorGroup); - Object[] xyz = node.getAttribute("xyz"); - double x = (double)xyz[0] * 20; - double y = (double)xyz[1] * 20; - lineNode.initXY(x, y); - } - } - - public Layout getDangerousLayout() - throws NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { - Object yahoo = accessField(viewer, "optLayout"); - Layout layout = accessField(yahoo, "layout"); - return layout; - } - - @SuppressWarnings("unchecked") - private static T accessField(Object myObj, String fieldName) - throws NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { - Class myClass = myObj.getClass(); - Field myField = getField(myClass, fieldName); - myField.setAccessible(true); - return (T) myField.get(myObj); - } - - private static Field getField(Class clazz, String fieldName) - throws NoSuchFieldException { - try { - return clazz.getDeclaredField(fieldName); - } catch (NoSuchFieldException e) { - Class superClass = clazz.getSuperclass(); - if (superClass == null) { - throw e; - } else { - return getField(superClass, fieldName); - } - } - } - - + private Graph graph; + public Viewer viewer; + private GraphicGraph ggraph; + SortedSet buffer; + DynamicFlowGraph displayedGraph; + + LinLog layout; + + private static int uniqId = 0; + public static final String DEFAULT_TITLE = "Cerebro"; + private static final int BUFFER_LIMIT = 300; + + public static DynamicDisplay init(String title, DynamicFlowGraph displayedGraph) { + System.setProperty("org.graphstream.ui.renderer", + "org.graphstream.ui.j2dviewer.J2DGraphRenderer"); + DynamicDisplay display = new DynamicDisplay(title, displayedGraph); + + display.setup(); + + display.launchDisplay(); + return display; + } + + private DynamicDisplay(String title, DynamicFlowGraph displayedGraph) { + graph = new MultiGraph(title); + buffer = Collections.synchronizedSortedSet(new TreeSet()); + this.displayedGraph = displayedGraph; + } + + private void setup() { + this.graph.setStrict(false); + this.graph.setAutoCreate(true); + File file = new File("css/stylesheet.css"); + String url = "url(file://" + file.getAbsolutePath() + ")"; + this.graph.addAttribute("ui.stylesheet", url); + this.graph.addAttribute("layout.quality", 4); + this.buffer.clear(); + } + + private void launchDisplay() { + this.viewer = this.graph.display(); + this.viewer.disableAutoLayout(); + + this.ggraph = this.viewer.getGraphicGraph(); + + View view = this.viewer.getDefaultView(); + + ViewerPipe fromViewer = this.viewer.newViewerPipe(); + ViewerEventListener viewerListener = + new ViewerEventListener(fromViewer, this.displayedGraph); + view.setMouseManager(viewerListener); + view.addMouseWheelListener(viewerListener); + fromViewer.addViewerListener(viewerListener); + fromViewer.addSink(this.graph); + } + + public void clear() { + this.graph.clear(); + } + + public synchronized void showDependence(int from, int to) { + showDependence(String.valueOf(from), String.valueOf(to), Double.NaN); + } + + public synchronized void showDependence(int from, int to, double weight) { + showDependence(String.valueOf(from), String.valueOf(to), weight); + } + + public void showDependence(String from, String to) { + showDependence(from, to, Double.NaN); + } + + public synchronized void showDependence(String from, String to, double weight) { + showDependence(from, Double.NaN, Double.NaN, to, Double.NaN, Double.NaN, weight); + } + + public synchronized void showDependence(int from, double fX, double fY, + int to, double tX, double tY, + double weight) { + showDependence(String.valueOf(from), fX, fY, String.valueOf(to), tX, tY, weight); + } + + public synchronized void showDependence(String from, double fX, double fY, + String to, double tX, double tY, + double weight) { + showNode(from, fX, fY); + showNode(to, tX, tY); + int id = uniqId++; + + try { + Node fromNode = graph.getNode(from); + if(fromNode == null || !fromNode.hasEdgeToward(to)) { + Edge edge = graph.addEdge(String.valueOf(id), from, to, true); + edge.addAttribute("ui.hide"); + + final String style = + String.format("fill-color: rgba(150,150,150,50);size: %spx;", + Double.isNaN(weight) ? 5 : plateau(weight)); + edge.addAttribute("ui.style", style); + } + } catch (IdAlreadyInUseException e) { } + } + + private double plateau(double value) { + Preconditions.checkArgument(!Double.isNaN(value)); + return 1.2*(1 + Math.log(value)); + } + + private void showNode(String nodeId, double x, double y) { + try { + Node node = graph.addNode(nodeId); + if(!Double.isNaN(x)) { + node.addAttribute("x", x); + } + + if(!Double.isNaN(y)) { + node.addAttribute("y", y); + } + + } catch(IdAlreadyInUseException nodeInUse) { } + } + + private void removeNode(String nodeId) { + try { + graph.removeNode(nodeId); + } catch(ElementNotFoundException nodeNotFound) { + // Do nothing for now. + } + } + + @SuppressWarnings("unused") + private synchronized void bufferNodes(int nodeId1, int nodeId2) { + buffer.add(nodeId1); + buffer.add(nodeId2); + + while(buffer.size() > BUFFER_LIMIT) { + int oldestNode = buffer.first(); + buffer.remove(oldestNode); + removeNode(String.valueOf(oldestNode)); + } + + for(Node node : graph.getEachNode()) { + if(node.getEdgeSet().size() == 0) { + buffer.remove(Integer.parseInt(node.getId())); + graph.removeNode(node); + } + } + } + + public static void play() throws IOException { } + + public void spitImage(int id) throws IOException { + FileSinkImages pic = new FileSinkImages(OutputType.PNG, Resolutions.VGA); + + pic.setLayoutPolicy(LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE); + pic.writeAll(this.graph, this.graph.getId() + id + ".png"); + } + + public void spitImage(String id) throws IOException { + FileSinkImages pic = new FileSinkImages(OutputType.PNG, Resolutions.VGA); + + pic.setLayoutPolicy(LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE); + pic.writeAll(this.graph, id + ".png"); + } + + public void weighEdges() { + double maxCount = displayedGraph.maxEdgeCount() + 1.0; + for(Edge edge : graph.getEachEdge()) { + Node from = edge.getSourceNode(); + Node to = edge.getTargetNode(); + int fromId = Integer.parseInt(from.toString()); + int toId = Integer.parseInt(to.toString()); + int count = displayedGraph.getEdgeCount(fromId, toId); + double weight = (maxCount - count)/maxCount; + edge.addAttribute("layout.weight", weight); + } + } + + public void colorNodes() { + int clusterCount = displayedGraph.getClusterCount(); + String[] palette = ColorPalette.generatePalette(clusterCount); + + for(Node node : graph.getEachNode()) { + int nodeId = Integer.valueOf(node.getId()); + SourceLineNode dynamicNode = displayedGraph.getNode(nodeId); + int colorIndex = dynamicNode.colorGroup; + if(colorIndex <= -1) { + continue; + } + + colorNode(palette, colorIndex, node); + } + } + + public void colorNodesByClass() { + int classCodeCount = displayedGraph.classCodeCount(); + String[] palette = ColorPalette.generatePalette(classCodeCount); + + for(Node node : graph.getEachNode()) { + int nodeId = Integer.valueOf(node.getId()); + int colorIndex = displayedGraph.getNodeClassCode(nodeId); + + if(colorIndex <= -1) { + continue; + } + + colorNode(palette, colorIndex, node); + } + } + + public void colorNodesByMethod() { + int methodCodeCount = displayedGraph.methodCodeCount(); + String[] palette = ColorPalette.generatePalette(methodCodeCount); + + for(Node node : graph.getEachNode()) { + int nodeId = Integer.valueOf(node.getId()); + int colorIndex = displayedGraph.getNodeMethodCode(nodeId); + + if(colorIndex <= -1) { + continue; + } + + colorNode(palette, colorIndex, node); + } + } + + private void colorNode(String[] palette, int colorIndex, Node node) { + Preconditions.checkNotNull(palette); + Preconditions.checkElementIndex(colorIndex, palette.length); + String color = palette[colorIndex % palette.length]; + String colorStyle = "fill-color: " + color + ";"; + node.setAttribute("ui.style", colorStyle); + } + + public void decolorNodes() { + for(Node node : graph.getEachNode()) { + node.setAttribute("ui.style", "fill-color:lightyellow;"); + } + } + + private int nodeSize = 4; + + public void expandNodes() { + if(nodeSize < 20) { + nodeSize += 1; + } + + for(Node node : graph.getEachNode()) { + node.setAttribute("ui.style", + String.format("size: %spx;", nodeSize)); + } + } + + public void shrinkNodes() { + if(nodeSize > 4) { + nodeSize -= 1; + } + + for(Node node : graph.getEachNode()) { + node.setAttribute("ui.style", + String.format("size: %spx;", nodeSize)); + } + } + + public void showEdges() { + for(Edge edge : graph.getEachEdge()) { + edge.removeAttribute("ui.hide"); + } + } + + public void hideEdges() { + for(Edge edge : graph.getEachEdge()) { + edge.addAttribute("ui.hide"); + } + } + + public void pinNodesOnDynamicFlowGraph() { + for(Node node : ggraph.getEachNode()) { + int nodeId = Integer.valueOf(node.getId()); + SourceLineNode lineNode = displayedGraph.getNode(nodeId); + // int colorGroup = displayedGraph.getNodeClassCode(nodeId); + // lineNode.initColorGroup(colorGroup); + Object[] xyz = node.getAttribute("xyz"); + double x = (double)xyz[0] * 20; + double y = (double)xyz[1] * 20; + lineNode.initXY(x, y); + } + } + + public Layout getDangerousLayout() + throws NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + Object yahoo = accessField(viewer, "optLayout"); + Layout layout = accessField(yahoo, "layout"); + return layout; + } + + @SuppressWarnings("unchecked") + private static T accessField(Object myObj, String fieldName) + throws NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + Class myClass = myObj.getClass(); + Field myField = getField(myClass, fieldName); + myField.setAccessible(true); + return (T) myField.get(myObj); + } + + private static Field getField(Class clazz, String fieldName) + throws NoSuchFieldException { + try { + return clazz.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + Class superClass = clazz.getSuperclass(); + if (superClass == null) { + throw e; + } else { + return getField(superClass, fieldName); + } + } + } + + public void setStartNode(){ + Node node = graph.getNode(0); + node.setAttribute("ui.style", + String.format("shape: %s; fill-color: %s;", "diamond", "white")); + +// n.addAttribute("ui.style", "size: 10px, 10px; shape: diamond; fill-color: blue;"); + } + } diff --git a/src/main/java/org/spideruci/cerebro/layout/LayoutFactory.java b/src/main/java/org/spideruci/cerebro/layout/LayoutFactory.java index 057acbe..f8af225 100644 --- a/src/main/java/org/spideruci/cerebro/layout/LayoutFactory.java +++ b/src/main/java/org/spideruci/cerebro/layout/LayoutFactory.java @@ -9,7 +9,8 @@ public class LayoutFactory { public static String layoutConfig = null; public static SpringBox getSpringBox() { - SpringBox layout = new SpringBox(); +// SpringBox layout = new SpringBox(); + NewSpringBox layout = new NewSpringBox(); layoutConfig = "-springbox"; return layout; } diff --git a/src/main/java/org/spideruci/cerebro/layout/NewSpringBox.java b/src/main/java/org/spideruci/cerebro/layout/NewSpringBox.java new file mode 100644 index 0000000..cd6e02c --- /dev/null +++ b/src/main/java/org/spideruci/cerebro/layout/NewSpringBox.java @@ -0,0 +1,55 @@ +package org.spideruci.cerebro.layout; + +import java.util.Random; + +import org.graphstream.ui.layout.springbox.NodeParticle; +import org.graphstream.ui.layout.springbox.implementations.SpringBox; +import org.graphstream.ui.layout.springbox.implementations.SpringBoxNodeParticle; + +public class NewSpringBox extends SpringBox { + + public NewSpringBox() { + // TODO Auto-generated constructor stub + } + + public NewSpringBox(boolean is3d) { + super(is3d); + // TODO Auto-generated constructor stub + } + + public NewSpringBox(boolean is3d, Random randomNumberGenerator) { + super(is3d, randomNumberGenerator); + // TODO Auto-generated constructor stub + } + + public double getK(){ + return k; + } + + public double getK1(){ + return K1; + } + + public double getK2(){ + return K2; + } + + public void setK(double d){ + k = d; + } + + public void setK1(double d){ + K1 = d; + } + + public void setK2(double d){ + K2 = d; + } + + @Override + public NodeParticle newNodeParticle(String id) { + return new NewSpringBoxNodeParticle(this, id); + } + + +} diff --git a/src/main/java/org/spideruci/cerebro/layout/NewSpringBoxNodeParticle.java b/src/main/java/org/spideruci/cerebro/layout/NewSpringBoxNodeParticle.java new file mode 100644 index 0000000..27fb876 --- /dev/null +++ b/src/main/java/org/spideruci/cerebro/layout/NewSpringBoxNodeParticle.java @@ -0,0 +1,101 @@ +package org.spideruci.cerebro.layout; + +import java.util.Iterator; + +import org.graphstream.ui.geom.Vector3; +import org.graphstream.ui.layout.springbox.EdgeSpring; +import org.graphstream.ui.layout.springbox.Energies; +import org.graphstream.ui.layout.springbox.NodeParticle; +import org.graphstream.ui.layout.springbox.implementations.SpringBox; +import org.graphstream.ui.layout.springbox.implementations.SpringBoxNodeParticle; +import org.miv.pherd.ParticleBox; +import org.miv.pherd.geom.Point3; + +public class NewSpringBoxNodeParticle extends SpringBoxNodeParticle { + + public NewSpringBoxNodeParticle(SpringBox box, String id) { + super(box, id); + // TODO Auto-generated constructor stub + } + + public NewSpringBoxNodeParticle(SpringBox box, String id, double x, double y, double z) { + super(box, id, x, y, z); + // TODO Auto-generated constructor stub + } + + @Override + protected void attraction(Vector3 delta) { + NewSpringBox box = (NewSpringBox) this.box; + boolean is3D = box.is3D(); + Energies energies = box.getEnergies(); + int neighbourCount = neighbours.size(); + + for (EdgeSpring edge : neighbours) { + if (!edge.ignored) { + NodeParticle other = edge.getOpposite(this); + Point3 opos = other.getPosition(); + + delta.set(opos.x - pos.x, opos.y - pos.y, is3D ? opos.z - pos.z + : 0); + + double len = delta.normalize(); + double k = box.getK() * edge.weight; + double factor = box.getK1() * (len - k); // original source + +// double factor = box.getK1() * edge.weight * edge.weight; +// double factor = box.getK1() * Math.log10(edge.weight); +// double factor = box.getK1() * Math.sqrt(edge.weight); + +// delta.scalarMult( factor ); +// delta.scalarMult(factor * (1f / (neighbourCount * 0.1f))); + delta.scalarMult(factor * (1f / (neighbourCount))); + // ^^^ XXX NEW inertia based on the node degree. This is one + // of the amelioration of the Spring-Box algorithm. Compare + // it to the Force-Atlas algorithm that does this on + // **repulsion**. + + disp.add(delta); + attE += factor; + energies.accumulateEnergy(factor); + } + } + + } + + @Override + protected void repulsionN2(Vector3 delta) { + NewSpringBox box = (NewSpringBox) this.box; + boolean is3D = box.is3D(); + ParticleBox nodes = box.getSpatialIndex(); + Energies energies = box.getEnergies(); + Iterator i = nodes.getParticleIdIterator(); + + while (i.hasNext()) { + NewSpringBoxNodeParticle node = (NewSpringBoxNodeParticle) nodes + .getParticle(i.next()); + + if (node != this) { + delta.set(node.pos.x - pos.x, node.pos.y - pos.y, + is3D ? node.pos.z - pos.z : 0); + + double len = delta.normalize(); + + if(len > 0) { + if (len < box.getK()) + len = box.getK(); // XXX NEW To prevent infinite + // repulsion. + + double factor = ((box.getK2() / (len * len)) * node.weight); //original source +// double factor = box.getK2() * Math.log10(node.weight); +// double factor = box.getK2() * Math.sqrt(node.weight); +// double factor = box.getK2() * node.weight; + + energies.accumulateEnergy(factor); // TODO check this + delta.scalarMult(-factor); + disp.add(delta); + } + } + } + } + +} diff --git a/src/main/java/org/spideruci/cerebro/layout/ViewerEventListener.java b/src/main/java/org/spideruci/cerebro/layout/ViewerEventListener.java index 9491db7..20f9966 100644 --- a/src/main/java/org/spideruci/cerebro/layout/ViewerEventListener.java +++ b/src/main/java/org/spideruci/cerebro/layout/ViewerEventListener.java @@ -16,218 +16,217 @@ import org.spideruci.cerebro.layout.model.SourceLineNode; public class ViewerEventListener extends DefaultMouseManager implements ViewerListener, MouseWheelListener { - - private static final double MIN_VIEW_PERCENT = 0.2; - private static final double MAX_VIEW_PERCENT = 4; - private static final double VIEW_PERCENT_STEP = 0.1; - - private final ViewerPipe eventSource2; - private final DynamicFlowGraph displayedGraph; - private Point3 previousPoint; - - public ViewerEventListener(ViewerPipe pipe, DynamicFlowGraph displayedGraph) { - this.eventSource2 = pipe; - this.displayedGraph = displayedGraph; - } - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - double rotation = e.getPreciseWheelRotation(); - - Camera cam = view.getCamera(); - // +ve is zoom out - // -ve is zoom in. - double viewPercent = cam.getViewPercent(); - if(rotation < 0) { // zoom in - viewPercent = viewPercent - VIEW_PERCENT_STEP; - viewPercent = - (viewPercent <= MIN_VIEW_PERCENT) ? MIN_VIEW_PERCENT - : viewPercent; - } else { // zoom out - viewPercent = viewPercent + VIEW_PERCENT_STEP; - viewPercent = - (viewPercent >= MAX_VIEW_PERCENT) ? MAX_VIEW_PERCENT - : viewPercent; - } - cam.setViewPercent(viewPercent); - } - - @Override - public void mouseClicked(MouseEvent e) { - eventSource2.pump(); - - if(e.isControlDown()) { - centerOn(e.getPoint()); - } - } - - private void centerOn(Point point) { - Camera camera = view.getCamera(); - int x = point.x; - int y = point.y; - Point3 newCenter = camera.transformPxToGu(x, y); - camera.setViewCenter(newCenter.x, newCenter.y, 0); - previousPoint = newCenter; - } - - @Override - public void mouseEntered(MouseEvent e) { - previousPoint = point3(e.getPoint()); - } - - @Override - public void mousePressed(MouseEvent e) { - boolean isShiftPressed = e.isShiftDown(); - if(!isShiftPressed) { - curElement = view.findNodeOrSpriteAt(e.getX(), e.getY()); - if (curElement != null) { - mouseButtonPressOnElement(curElement, e); - } - - previousPoint = point3(e.getPoint()); - } - - curElement = view.findNodeOrSpriteAt(e.getX(), e.getY()); - - if (curElement != null) { - mouseButtonPressOnElement(curElement, e); - } else { - x1 = e.getX(); - y1 = e.getY(); - mouseButtonPress(e); - view.beginSelectionAt(x1, y1); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - - boolean isShiftPressed = e.isShiftDown(); - if(!isShiftPressed) { - if (curElement != null) { - mouseButtonReleaseOffElement(curElement, e); - curElement = null; - } - return; - } - - if (curElement != null) { - mouseButtonReleaseOffElement(curElement, e); - curElement = null; - } else { - float x2 = e.getX(); - float y2 = e.getY(); - float t; - - if (x1 > x2) { - t = x1; - x1 = x2; - x2 = t; - } - if (y1 > y2) { - t = y1; - y1 = y2; - y2 = t; - } - - mouseButtonRelease(e, view.allNodesOrSpritesIn(x1, y1, x2, y2)); - view.endSelectionAt(x2, y2); - } - - boolean nodesWereSelected = false; - System.out.println("## Selection of Nodes is ..."); - - HashMap freq = new HashMap<>(); - for(Node node : graph) { - if(node.hasAttribute("ui.selected")) { - nodesWereSelected = true; - String nodeId = node.toString(); - if(displayedGraph != null) { - SourceLineNode lineNode = displayedGraph.getNode(Integer.parseInt(nodeId)); - String sourceLine = lineNode.toString(); - if(!freq.containsKey(sourceLine)) { - freq.put(sourceLine, 0); - } - - int f = freq.get(sourceLine); - freq.put(sourceLine, f + 1); -// System.out.println(sourceLine); - } else { - System.out.println(nodeId); - } - } - } - - for(String line : freq.keySet()) { - System.out.println(line + " " + freq.get(line)); - } - - if(!nodesWereSelected) { - System.out.println("EMPTY."); - } - } - - @Override - public void mouseDragged(MouseEvent e) { - boolean isShiftPressed = e.isShiftDown(); - if(!isShiftPressed) { - if (curElement != null) { - elementMoving(curElement, e); - } - Point3 currentPoint = point3(e.getPoint()); - double xDelta = (currentPoint.x - previousPoint.x) / 1.5; - double yDelta = (currentPoint.y - previousPoint.y) / 1.5; - pan(xDelta, yDelta); - previousPoint = currentPoint; - } else { - if (curElement != null) { - elementMoving(curElement, e); - } else { - view.selectionGrowsAt(e.getX(), e.getY()); - -// System.out.println(e.getPoint().toString()); - } - } - } - - private void pan(double xDelta, double yDelta) { - Camera camera = view.getCamera(); - Point3 point = camera.getViewCenter(); - double x = point.x - xDelta; - double y = point.y - yDelta; - camera.setViewCenter(x, y, 0); - } - - - - private Point3 point3(Point point) { - Camera camera = view.getCamera(); - return camera.transformPxToGu(point.x, point.y); - } - - - @Override - public void buttonPushed(String id) { - String nodeId = id; - try { - SourceLineNode node = displayedGraph.getNode(Integer.parseInt(nodeId)); - System.out.println(node.toString()); - throw new Exception(); - } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("OKAY! Something went wrong." + - "\nFeel free to report this exception." + - "\nContinue using the command menu... "); - System.out.println(Commands.mainMenu); - } - - } - - @Override - public void buttonReleased(String id) { - - } - - @Override - public void viewClosed(String viewName) { } + + private static final double MIN_VIEW_PERCENT = 0.2; + private static final double MAX_VIEW_PERCENT = 4; + private static final double VIEW_PERCENT_STEP = 0.1; + + private final ViewerPipe eventSource2; + private final DynamicFlowGraph displayedGraph; + private Point3 previousPoint; + + public ViewerEventListener(ViewerPipe pipe, DynamicFlowGraph displayedGraph) { + this.eventSource2 = pipe; + this.displayedGraph = displayedGraph; + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + double rotation = e.getPreciseWheelRotation(); + + Camera cam = view.getCamera(); + // +ve is zoom out + // -ve is zoom in. + double viewPercent = cam.getViewPercent(); + if(rotation < 0) { // zoom in + viewPercent = viewPercent - VIEW_PERCENT_STEP; + viewPercent = + (viewPercent <= MIN_VIEW_PERCENT) ? MIN_VIEW_PERCENT + : viewPercent; + } else { // zoom out + viewPercent = viewPercent + VIEW_PERCENT_STEP; + viewPercent = + (viewPercent >= MAX_VIEW_PERCENT) ? MAX_VIEW_PERCENT + : viewPercent; + } + cam.setViewPercent(viewPercent); + } + + @Override + public void mouseClicked(MouseEvent e) { + eventSource2.pump(); + + if(e.isControlDown()) { + centerOn(e.getPoint()); + } + } + + private void centerOn(Point point) { + Camera camera = view.getCamera(); + int x = point.x; + int y = point.y; + Point3 newCenter = camera.transformPxToGu(x, y); + camera.setViewCenter(newCenter.x, newCenter.y, 0); + previousPoint = newCenter; + } + + @Override + public void mouseEntered(MouseEvent e) { + previousPoint = point3(e.getPoint()); + } + + @Override + public void mousePressed(MouseEvent e) { + boolean isShiftPressed = e.isShiftDown(); + if(!isShiftPressed) { + curElement = view.findNodeOrSpriteAt(e.getX(), e.getY()); + if (curElement != null) { + mouseButtonPressOnElement(curElement, e); + } + + previousPoint = point3(e.getPoint()); + } + + curElement = view.findNodeOrSpriteAt(e.getX(), e.getY()); + + if (curElement != null) { + mouseButtonPressOnElement(curElement, e); + } else { + x1 = e.getX(); + y1 = e.getY(); + mouseButtonPress(e); + view.beginSelectionAt(x1, y1); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + + boolean isShiftPressed = e.isShiftDown(); + if(!isShiftPressed) { + if (curElement != null) { + mouseButtonReleaseOffElement(curElement, e); + curElement = null; + } + return; + } + + if (curElement != null) { + mouseButtonReleaseOffElement(curElement, e); + curElement = null; + } else { + float x2 = e.getX(); + float y2 = e.getY(); + float t; + + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + mouseButtonRelease(e, view.allNodesOrSpritesIn(x1, y1, x2, y2)); + view.endSelectionAt(x2, y2); + } + + boolean nodesWereSelected = false; + System.out.println("## Selection of Nodes is ..."); + + HashMap freq = new HashMap<>(); + for(Node node : graph) { + if(node.hasAttribute("ui.selected")) { + nodesWereSelected = true; + String nodeId = node.toString(); + if(displayedGraph != null) { + SourceLineNode lineNode = displayedGraph.getNode(Integer.parseInt(nodeId)); + String sourceLine = lineNode.toString(); + if(!freq.containsKey(sourceLine)) { + freq.put(sourceLine, 0); + } + + int f = freq.get(sourceLine); + freq.put(sourceLine, f + 1); + // System.out.println(sourceLine); + } else { + System.out.println(nodeId); + } + } + } + + for(String line : freq.keySet()) { + System.out.println(line + " " + freq.get(line)); + } + + if(!nodesWereSelected) { + System.out.println("EMPTY."); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + boolean isShiftPressed = e.isShiftDown(); + if(!isShiftPressed) { + if (curElement != null) { + elementMoving(curElement, e); + } + Point3 currentPoint = point3(e.getPoint()); + double xDelta = (currentPoint.x - previousPoint.x) / 1.5; + double yDelta = (currentPoint.y - previousPoint.y) / 1.5; + pan(xDelta, yDelta); + previousPoint = currentPoint; + } else { + if (curElement != null) { + elementMoving(curElement, e); + } else { + view.selectionGrowsAt(e.getX(), e.getY()); + + // System.out.println(e.getPoint().toString()); + } + } + } + + private void pan(double xDelta, double yDelta) { + Camera camera = view.getCamera(); + Point3 point = camera.getViewCenter(); + double x = point.x - xDelta; + double y = point.y - yDelta; + camera.setViewCenter(x, y, 0); + } + + + + private Point3 point3(Point point) { + Camera camera = view.getCamera(); + return camera.transformPxToGu(point.x, point.y); + } + + + @Override + public void buttonPushed(String id) { + String nodeId = id; + try { + SourceLineNode node = displayedGraph.getNode(Integer.parseInt(nodeId)); + System.out.println(node.toString()); + } catch (Exception ex) { + ex.printStackTrace(); + System.out.println("OKAY! Something went wrong." + + "\nFeel free to report this exception." + + "\nContinue using the command menu... "); + System.out.println(Commands.mainMenu); + } + + } + + @Override + public void buttonReleased(String id) { + + } + + @Override + public void viewClosed(String viewName) { } } diff --git a/src/main/java/org/spideruci/cerebro/layout/model/DynamicFlowGraph.java b/src/main/java/org/spideruci/cerebro/layout/model/DynamicFlowGraph.java index 7c6cf7e..3fe511e 100644 --- a/src/main/java/org/spideruci/cerebro/layout/model/DynamicFlowGraph.java +++ b/src/main/java/org/spideruci/cerebro/layout/model/DynamicFlowGraph.java @@ -50,7 +50,7 @@ public SourceLineNode addNode(TraceEvent event) { classCodes.add(className); } - String methodName = className + "." + lineNode.methodName; + String methodName = className + "." + lineNode.methodName(); int methodCode = methodCodes.indexOf(methodName); if(methodCode == -1) { methodCodes.add(methodName); @@ -69,13 +69,13 @@ public SourceLineNode addNode(SourceLineNode node) { id = id + 1; } - String className = node.className; + String className = node.className(); int classCode = classCodes.indexOf(className); if(classCode == -1) { classCodes.add(className); } - String methodName = className + "." + node.methodName; + String methodName = className + "." + node.methodName(); int methodCode = methodCodes.indexOf(methodName); if(methodCode == -1) { methodCodes.add(methodName); diff --git a/src/main/java/org/spideruci/cerebro/layout/model/SourceLineFlow.java b/src/main/java/org/spideruci/cerebro/layout/model/SourceLineFlow.java index a0c3fb7..5e57130 100644 --- a/src/main/java/org/spideruci/cerebro/layout/model/SourceLineFlow.java +++ b/src/main/java/org/spideruci/cerebro/layout/model/SourceLineFlow.java @@ -9,7 +9,7 @@ public class SourceLineFlow { public static SourceLineFlow flow(SourceLineNode start, SourceLineNode end, double weight) { - SourceLineFlow flow = new SourceLineFlow(start.id, end.id, + SourceLineFlow flow = new SourceLineFlow(start.id(), end.id(), start.x, start.y, end.x, end.y, weight); return flow; } diff --git a/src/main/java/org/spideruci/cerebro/layout/model/SourceLineNode.java b/src/main/java/org/spideruci/cerebro/layout/model/SourceLineNode.java index aec3a48..e9bbfd0 100644 --- a/src/main/java/org/spideruci/cerebro/layout/model/SourceLineNode.java +++ b/src/main/java/org/spideruci/cerebro/layout/model/SourceLineNode.java @@ -5,10 +5,10 @@ import com.google.common.base.Preconditions; public class SourceLineNode implements Clusterable { - public final String className; - public final String methodName; - public final int lineNum; - public int id; + private final String className; + private final String methodName; + private final int lineNum; + private int id; public int colorGroup; public float x; public float y;