From e9a4ad659e7d8c5eefc6df3b5415607f1a244ac2 Mon Sep 17 00:00:00 2001 From: Nils Christian Ehmke <nie@informatik.uni-kiel.de> Date: Thu, 29 Nov 2012 21:22:57 +0100 Subject: [PATCH] Made the autolayout threadsafe. --- .../common/layout/GraphFlowLayouter.java | 126 +++++++++--------- .../view/CurrentAnalysisEditorGraphBean.java | 32 +++-- 2 files changed, 83 insertions(+), 75 deletions(-) diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/layout/GraphFlowLayouter.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/layout/GraphFlowLayouter.java index 780fca4b..03ed18fa 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/layout/GraphFlowLayouter.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/layout/GraphFlowLayouter.java @@ -19,10 +19,6 @@ package kieker.webgui.common.layout; import java.util.ArrayList; import java.util.List; -import kieker.webgui.common.exception.InvalidInputSizeException; -import kieker.webgui.common.exception.UninitializedGraphException; - - import de.cau.cs.kieler.core.alg.BasicProgressMonitor; import de.cau.cs.kieler.core.alg.IKielerProgressMonitor; import de.cau.cs.kieler.core.kgraph.KEdge; @@ -38,6 +34,9 @@ import de.cau.cs.kieler.kiml.options.PortConstraints; import de.cau.cs.kieler.kiml.util.KimlUtil; import de.cau.cs.kieler.klay.layered.LayeredLayoutProvider; +import kieker.webgui.common.exception.InvalidInputSizeException; +import kieker.webgui.common.exception.UninitializedGraphException; + import org.eclipse.emf.common.util.EList; /** @@ -49,15 +48,6 @@ import org.eclipse.emf.common.util.EList; */ public final class GraphFlowLayouter { - /** - * An array containing the child node and the ports from left to right. - */ - private static List<Object>[] children; - /** - * An array containing edges. This way we can return edge information in the same order. - */ - private static KEdge[] edges; - /** * Private constructor as this is a utility class. */ @@ -73,16 +63,11 @@ public final class GraphFlowLayouter { * @return The constructed Graph * @throws InvalidInputSizeException */ - private static KNode addNodes(final String input) throws InvalidInputSizeException { - final String[] positions = input.split(" "); - - // set up root - final KNode graph = KimlUtil.createInitializedNode(); - graph.getData(KShapeLayout.class).setProperty(LayoutOptions.EDGE_ROUTING, EdgeRouting.ORTHOGONAL); + private static void addNodes(final String[] positions, final LayoutInformation layoutInformation) throws InvalidInputSizeException { + layoutInformation.graph.getData(KShapeLayout.class).setProperty(LayoutOptions.EDGE_ROUTING, EdgeRouting.ORTHOGONAL); // prepare array of lists List<Object> child; - GraphFlowLayouter.children = new ArrayList[positions.length / 2]; final int dimHalf = Integer.parseInt(positions[0]); final int dim = dimHalf * 2; @@ -112,10 +97,10 @@ public final class GraphFlowLayouter { // create Node node = KimlUtil.createInitializedNode(); - node.setParent(graph); + node.setParent(layoutInformation.graph); child = new ArrayList<Object>(); - GraphFlowLayouter.children[i] = child; + layoutInformation.children[i] = child; child.add(node); // set node dimensions @@ -158,8 +143,6 @@ public final class GraphFlowLayouter { } i++; } - - return graph; } /** @@ -180,20 +163,15 @@ public final class GraphFlowLayouter { * @throws InvalidInputSizeException * If the input size is invalid. */ - private static void addEdges(final String input) throws UninitializedGraphException, InvalidInputSizeException { - final String[] edgeInfo = input.split(" "); - + private static void addEdges(final String[] edgeInfo, final LayoutInformation layoutInformation) throws UninitializedGraphException, InvalidInputSizeException { // cannot add edges if no graph was constructed - if (GraphFlowLayouter.children == null) { + if (layoutInformation.children == null) { throw new UninitializedGraphException(); } if ((edgeInfo.length % 4) != 0) { throw new InvalidInputSizeException(); } - // init edge Array - GraphFlowLayouter.edges = new KEdge[edgeInfo.length / 4]; - // set up loop variables KEdge edge; int sourceID; @@ -208,13 +186,13 @@ public final class GraphFlowLayouter { // read from String sourceID = Integer.parseInt(edgeInfo[e++]); targetID = Integer.parseInt(edgeInfo[e++]); - sourcePort = (KPort) GraphFlowLayouter.children[sourceID].get(1 + Integer.parseInt(edgeInfo[e++])); - targetPort = (KPort) GraphFlowLayouter.children[targetID].get(1 + Integer.parseInt(edgeInfo[e++])); + sourcePort = (KPort) layoutInformation.children[sourceID].get(1 + Integer.parseInt(edgeInfo[e++])); + targetPort = (KPort) layoutInformation.children[targetID].get(1 + Integer.parseInt(edgeInfo[e++])); // add edge to graph edge = KimlUtil.createInitializedEdge(); - edge.setSource((KNode) GraphFlowLayouter.children[sourceID].get(0)); - edge.setTarget((KNode) GraphFlowLayouter.children[targetID].get(0)); + edge.setSource((KNode) layoutInformation.children[sourceID].get(0)); + edge.setTarget((KNode) layoutInformation.children[targetID].get(0)); // set ports of edge edge.setSourcePort(sourcePort); @@ -222,11 +200,24 @@ public final class GraphFlowLayouter { edge.setTargetPort(targetPort); targetPort.getEdges().add(edge); - GraphFlowLayouter.edges[ea++] = edge; + layoutInformation.edges[ea++] = edge; } } + private static LayoutInformation assembleLayoutInformation(final String nodesStr, final String edgesStr) { + final String[] edgeInfo = edgesStr.split(" "); + final String[] positions = nodesStr.split(" "); + final ArrayList[] children = new ArrayList[positions.length / 2]; + final KEdge[] edges = new KEdge[edgeInfo.length / 4]; + final LayoutInformation layoutInformation = new LayoutInformation(KimlUtil.createInitializedNode(), children, edges); + + GraphFlowLayouter.addNodes(positions, layoutInformation); + GraphFlowLayouter.addEdges(edgeInfo, layoutInformation); + + return layoutInformation; + } + /** * This method takes two Strings, describing some basic graph information, and constructs a KGraph, which is then layouted by a Kieler algorithm. * @@ -236,34 +227,21 @@ public final class GraphFlowLayouter { * A String containing connection information of edges. * @return A String of space separated node positions. */ - public static String layoutGraph(final String nodes, final String edges) { - KNode graph; - try { - graph = GraphFlowLayouter.addNodes(nodes); - GraphFlowLayouter.addEdges(edges); - } catch (final InvalidInputSizeException ie) { - System.err.println(ie.getMessage()); - return null; - } catch (final UninitializedGraphException ue) { - System.err.println(ue.getMessage()); - return null; - } + public static String layoutGraph(final String nodes, final String edges) throws UninitializedGraphException, InvalidInputSizeException { + final LayoutInformation layoutInformation = GraphFlowLayouter.assembleLayoutInformation(nodes, edges); - // create a progress monitor + // Create a progress monitor final IKielerProgressMonitor progressMonitor = new BasicProgressMonitor(); - // create the layout provider + // Create the layout provider final AbstractLayoutProvider layoutProvider = new LayeredLayoutProvider(); - // perform layout on the created graph - layoutProvider.doLayout(graph, progressMonitor); - - // output layout information - // GraphFlowLayouter.printLayoutInfo(graph); + // Perform layout on the created graph + layoutProvider.doLayout(layoutInformation.graph, progressMonitor); // convert layouted graph positions to String - final String layoutedGraph = GraphFlowLayouter.getPositions(graph); - final String bendPoints = GraphFlowLayouter.getBendPoints(); + final String layoutedGraph = GraphFlowLayouter.getPositions(layoutInformation); + final String bendPoints = GraphFlowLayouter.getBendPoints(layoutInformation); return layoutedGraph + "#" + bendPoints; } @@ -274,11 +252,11 @@ public final class GraphFlowLayouter { * The graph with at least one child * @return The constructed string */ - private static String getPositions(final KNode graph) { + private static String getPositions(final LayoutInformation layoutInformation) { final StringBuilder sb = new StringBuilder(); KShapeLayout layout; - for (final KNode node : graph.getChildren()) { + for (final KNode node : layoutInformation.graph.getChildren()) { layout = node.getData(KShapeLayout.class); final int x = Math.round(layout.getXpos() + (layout.getWidth() / 2)); final int y = Math.round(layout.getYpos() + (layout.getHeight() / 2)); @@ -292,15 +270,17 @@ public final class GraphFlowLayouter { } /** - * Iterates all edges and creates a semicolon separated String which contains bend points of all edges. + * This method iterates through all edges of the given object and creates a semicolon separated String containing bend points of all edges. * - * @return The bend point String + * @param layoutInformation + * The object containing the information about the graph and the layout. + * @return The string containing the bend points. */ - private static String getBendPoints() { + private static String getBendPoints(final LayoutInformation layoutInformation) { final StringBuilder sb = new StringBuilder(); // iterate edges - for (final KEdge edge : GraphFlowLayouter.edges) { + for (final KEdge edge : layoutInformation.edges) { final KEdgeLayout layout = edge.getData(KEdgeLayout.class); final EList<KPoint> bendPoints = layout.getBendPoints(); @@ -318,4 +298,24 @@ public final class GraphFlowLayouter { return sb.toString(); } + + private static class LayoutInformation { + + public final KNode graph; + /** + * An array containing the child node and the ports from left to right. + */ + public final List<Object>[] children; + /** + * An array containing edges. This way we can return edge information in the same order. + */ + public final KEdge[] edges; + + public LayoutInformation(final KNode graph, final List<Object>[] children, final KEdge[] edges) { + this.graph = graph; + this.children = children; + this.edges = edges; + } + + } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java index 1dfaffb0..39a9ae0b 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java @@ -34,6 +34,8 @@ import kieker.analysis.model.analysisMetaModel.MIRepositoryConnector; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; import kieker.monitoring.core.registry.Registry; +import kieker.webgui.common.exception.InvalidInputSizeException; +import kieker.webgui.common.exception.UninitializedGraphException; import kieker.webgui.common.layout.GraphFlowLayouter; import org.primefaces.context.RequestContext; @@ -205,18 +207,24 @@ public final class CurrentAnalysisEditorGraphBean { * This method uses the given parameters (via request parameter map) to calculate a new layout for the graph and use this layout. */ public synchronized void autoLayout() { - // Get the parameters - final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); - - final String nodes = paramMap.get("nodes"); - final String edges = paramMap.get("edges"); - - // Calculate the layout - final String newLayout = GraphFlowLayouter.layoutGraph(nodes, edges); - - // Now use it - RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_LOAD_FROM_LAYOUT, newLayout)); - RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_REFRESH_GRAPH); + try { + // Get the parameters + final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); + + final String nodes = paramMap.get("nodes"); + final String edges = paramMap.get("edges"); + + // Calculate the layout + final String newLayout = GraphFlowLayouter.layoutGraph(nodes, edges); + + // Now use it + RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_LOAD_FROM_LAYOUT, newLayout)); + RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_REFRESH_GRAPH); + } catch (final UninitializedGraphException ex) { + CurrentAnalysisEditorGraphBean.LOG.warn("Autolayout failed.", ex); + } catch (final InvalidInputSizeException ex) { + CurrentAnalysisEditorGraphBean.LOG.warn("Autolayout failed.", ex); + } } /** -- GitLab