You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by hi...@apache.org on 2016/09/20 22:34:52 UTC
[35/35] incubator-geode git commit: GEODE-37 changed sequence.gemfire
to org.apache.geode
GEODE-37 changed sequence.gemfire to org.apache.geode
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/5ba853da
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/5ba853da
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/5ba853da
Branch: refs/heads/develop
Commit: 5ba853daac384a5d8a0b6490cedbd556682e7034
Parents: 06436db
Author: Hitesh Khamesra <hk...@pivotal.io>
Authored: Mon Sep 19 13:45:10 2016 -0700
Committer: Hitesh Khamesra <hk...@pivotal.io>
Committed: Tue Sep 20 14:29:51 2016 -0700
----------------------------------------------------------------------
.../java/org/apache/geode/sequence/Arrow.java | 124 +++++++
.../geode/sequence/DefaultLineMapper.java | 41 +++
.../geode/sequence/GemfireSequenceDisplay.java | 335 +++++++++++++++++++
.../apache/geode/sequence/HydraLineMapper.java | 134 ++++++++
.../org/apache/geode/sequence/Lifeline.java | 98 ++++++
.../apache/geode/sequence/LifelineState.java | 114 +++++++
.../org/apache/geode/sequence/LineMapper.java | 35 ++
.../geode/sequence/SelectGraphDialog.java | 155 +++++++++
.../apache/geode/sequence/SequenceDiagram.java | 315 +++++++++++++++++
.../apache/geode/sequence/SequencePanel.java | 83 +++++
.../apache/geode/sequence/StateColorMap.java | 66 ++++
.../org/apache/geode/sequence/TimeAxis.java | 122 +++++++
.../org/apache/geode/sequence/ZoomingPanel.java | 188 +++++++++++
.../test/java/org/apache/sequence/Arrow.java | 124 -------
.../test/java/org/apache/sequence/Lifeline.java | 98 ------
.../java/org/apache/sequence/LifelineState.java | 114 -------
.../java/org/apache/sequence/LineMapper.java | 35 --
.../org/apache/sequence/SequenceDiagram.java | 315 -----------------
.../java/org/apache/sequence/SequencePanel.java | 83 -----
.../java/org/apache/sequence/StateColorMap.java | 66 ----
.../test/java/org/apache/sequence/TimeAxis.java | 122 -------
.../java/org/apache/sequence/ZoomingPanel.java | 188 -----------
.../sequence/gemfire/DefaultLineMapper.java | 41 ---
.../gemfire/GemfireSequenceDisplay.java | 335 -------------------
.../sequence/gemfire/HydraLineMapper.java | 134 --------
.../sequence/gemfire/SelectGraphDialog.java | 155 ---------
26 files changed, 1810 insertions(+), 1810 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/Arrow.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/Arrow.java b/geode-core/src/test/java/org/apache/geode/sequence/Arrow.java
new file mode 100644
index 0000000..060af88
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/Arrow.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.awt.*;
+import java.awt.geom.GeneralPath;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Nov 12, 2010
+ * Time: 12:02:20 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class Arrow {
+ private static int ARROW_WIDTH=10;
+ private static int CIRCLE_WIDTH=6;
+ private static int LABEL_OFFSET=10;
+
+ private final String label;
+ private final LifelineState startingState;
+ private final LifelineState endingState;
+
+ public Arrow(String label, LifelineState startingState, LifelineState endingState) {
+ this.label = label;
+ this.startingState = startingState;
+ this.endingState = endingState;
+ }
+
+
+ public void paint(Graphics2D g) {
+ Rectangle boundary = g.getClipBounds();
+ int y = endingState.getStartY();
+
+ //don't paint if we're not in the clip area
+ if(y + ARROW_WIDTH < boundary.getMinY() || y - ARROW_WIDTH > boundary.getMaxY()) {
+ return;
+ }
+
+ //TODO - we need to clip by X coordinate as well.
+
+ boolean isReflexsive = getStartingLine() == getEndingLine();
+ if(isReflexsive) {
+ paintReflexive(g);
+ } else {
+ paintNormal(g);
+ }
+ }
+
+ private Lifeline getStartingLine() {
+ return startingState.getLine();
+ }
+
+ private Lifeline getEndingLine() {
+ return endingState.getLine();
+ }
+
+ private void paintReflexive(Graphics2D g) {
+ Lifeline startingLine = getStartingLine();
+ int x = startingLine.getX();
+ int y = endingState.getStartY();
+
+ g.drawArc(x + startingLine.getWidth() - ARROW_WIDTH / 2, y - ARROW_WIDTH, ARROW_WIDTH, ARROW_WIDTH, 90, -180);
+ g.drawString(label, x + startingLine.getWidth() + LABEL_OFFSET, y);
+// GeneralPath path = new GeneralPath();
+// path.moveTo(x, y - ARROW_WIDTH);
+// path.quadTo(x, y - ARROW_WIDTH);
+ }
+
+ private void paintNormal(Graphics2D g) {
+ Lifeline startingLine = getStartingLine();
+ Lifeline endingLine = getEndingLine();
+ int x1 = startingLine.getX();
+ int x2 = endingLine.getX();
+ int y = endingState.getStartY();
+
+ if(x2 > x1) {
+ int startX = x1 + startingLine.getWidth();
+ int endX = x2;
+
+ GeneralPath path = new GeneralPath();
+ path.moveTo(startX, y);
+ path.lineTo(endX, y);
+ path.lineTo(endX - ARROW_WIDTH, y - ARROW_WIDTH);
+ path.moveTo(endX, y);
+ path.lineTo(endX - ARROW_WIDTH, y + ARROW_WIDTH);
+ g.draw(path);
+ g.fillArc(startX, y - CIRCLE_WIDTH/2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360);
+ g.drawString(label, startX + LABEL_OFFSET, y - LABEL_OFFSET);
+ } else {
+ int startX = x1;
+ int endX = x2 + endingLine.getWidth();
+
+ GeneralPath path = new GeneralPath();
+ path.moveTo(startX, y);
+ path.lineTo(endX, y);
+ path.lineTo(endX + ARROW_WIDTH, y - ARROW_WIDTH);
+ path.moveTo(endX, y);
+ path.lineTo(endX + ARROW_WIDTH, y + ARROW_WIDTH);
+ g.draw(path);
+ int labelWidth = g.getFontMetrics().stringWidth(label);
+ g.fillArc(startX - CIRCLE_WIDTH/2, y - CIRCLE_WIDTH/2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360);
+ g.drawString(label, startX - LABEL_OFFSET - labelWidth, y - LABEL_OFFSET);
+ }
+ }
+
+ public LifelineState getStartingState() {
+ return startingState;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/DefaultLineMapper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/DefaultLineMapper.java b/geode-core/src/test/java/org/apache/geode/sequence/DefaultLineMapper.java
new file mode 100644
index 0000000..fcec33c
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/DefaultLineMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.geode.sequence.LineMapper;
+
+/**
+ * A lifeline mapper that just returns a shortened version of
+ * a member id.
+ *
+ */
+public class DefaultLineMapper implements LineMapper {
+ private static Pattern MEMBER_ID_RE = Pattern.compile(".*\\((\\d+)(:admin)?(:loner)?\\).*:\\d+(/\\d+|.*:.*)");
+
+ public String getShortNameForLine(String name) {
+ Matcher matcher = MEMBER_ID_RE.matcher(name);
+ if(matcher.matches()) {
+ return matcher.group(1);
+ } else {
+ return name;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/GemfireSequenceDisplay.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/GemfireSequenceDisplay.java b/geode-core/src/test/java/org/apache/geode/sequence/GemfireSequenceDisplay.java
new file mode 100644
index 0000000..7fb06b9
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/GemfireSequenceDisplay.java
@@ -0,0 +1,335 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import org.apache.geode.internal.sequencelog.GraphType;
+import org.apache.geode.internal.sequencelog.io.Filter;
+import org.apache.geode.internal.sequencelog.io.GraphReader;
+import org.apache.geode.internal.sequencelog.model.*;
+import org.apache.geode.sequence.*;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ */
+public class GemfireSequenceDisplay {
+
+ private JLabel selectedGraphsLabel;
+ private SelectGraphDialog selectGraphDialog;
+
+ private Map<GraphID, Map<String, Lifeline>> lineMap = new HashMap();
+ private Map<GraphID, List<Arrow>> arrowMap = new HashMap();
+ private SequenceDiagram sequenceDiagram;
+ private JFrame frame;
+ private SequencePanel sequencePanel;
+
+ /**
+ * Create the GUI and show it. For thread safety,
+ * this method should be invoked from the
+ * event-dispatching thread.
+ *
+ * @param graphs
+ * @param lineMapper
+ */
+ private void createAndShowGUI(final GraphSet graphs, LineMapper lineMapper) {
+ //Create and set up the window.
+
+ frame = new JFrame("SequenceDiagram");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ createMenu();
+ createSequenceDiagram(graphs, lineMapper);
+ createSequenceMaps(graphs);
+
+ createSelectGraphDialog(graphs);
+
+ // for (GraphID id : graphs.getMap().keySet()) {
+ // showSubDiagram(id);
+ //
+ // }
+
+ sequencePanel = new SequencePanel(sequenceDiagram);
+ frame.getContentPane().add(sequencePanel);
+ //Display the window.
+ frame.pack();
+ frame.setVisible(true);
+ showGraphSelector();
+ }
+
+ private void createMenu() {
+ JMenuBar menuBar = new JMenuBar();
+
+ JMenu sequenceMenu = new JMenu("Sequence");
+ sequenceMenu.setMnemonic(KeyEvent.VK_S);
+ sequenceMenu.getAccessibleContext().setAccessibleDescription(
+ "The only menu in this program that has menu items");
+ menuBar.add(sequenceMenu);
+ JMenuItem selectGraphs = new JMenuItem("Choose Graphs",
+ KeyEvent.VK_G);
+ selectGraphs.setAccelerator(KeyStroke.getKeyStroke(
+ KeyEvent.VK_G, ActionEvent.ALT_MASK));
+ selectGraphs.getAccessibleContext().setAccessibleDescription(
+ "Select what graphs to display");
+ selectGraphs.setActionCommand("selectgraphs");
+ selectGraphs.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ showGraphSelector();
+ }
+ });
+
+ sequenceMenu.add(selectGraphs);
+ frame.setJMenuBar(menuBar);
+ }
+
+ private void createSelectGraphDialog(final GraphSet graphs) {
+ selectGraphDialog = new SelectGraphDialog(graphs);
+ selectGraphDialog.addSelectionListener(new SelectGraphDialog.SelectionListener() {
+
+ public void selectionChanged(List<GraphID> selectedIds) {
+ updateGraphs(selectedIds);
+ }
+ });
+ selectGraphDialog.pack();
+ }
+
+ private void updateGraphs(List<GraphID> selectedIds) {
+ List<GraphID> existingDiagrams =(List) sequenceDiagram.getSubDiagramsNames();
+ for(GraphID id : selectedIds) {
+ showSubDiagram(id);
+ existingDiagrams.remove(id);
+ }
+ for(GraphID id : existingDiagrams) {
+ hideSubDiagram(id);
+ }
+
+ sequenceDiagram.resizeMe(sequenceDiagram.getWidth(), sequenceDiagram.getHeight());
+ sequencePanel.revalidate();
+ sequencePanel.repaint();
+ // sequenceDiagram.revalidate();
+ // sequenceDiagram.repaint();
+ }
+
+ private void showGraphSelector() {
+ selectGraphDialog.setVisible(true);
+ }
+
+ private void hideGraphSelector() {
+ selectGraphDialog.setVisible(false);
+ }
+
+ // private static SequenceDiagram createSequenceDiagram() {
+ // long startTime = System.currentTimeMillis();
+ // List<Lifeline> lines = new ArrayList<Lifeline>();
+ // List<Arrow> arrows = new ArrayList<Arrow>();
+ // for(int i =0 ; i < 10; i++) {
+ // List<LifelineState> states = new ArrayList<LifelineState>();
+ // for(int j =0; j < 5; j++) {
+ // LifelineState state = new LifelineState(startTime + 20* j, startTime + 20 * j + 20);
+ // states.add(state);
+ // }
+ // Lifeline line = new Lifeline(i, states);
+ // lines.add(line);
+ //
+ // if(i > 0) {
+ // Arrow arrow = new Arrow("arrow" + i, line, lines.get(i - 1), line.getStates().get(2));
+ // arrows.add(arrow);
+ // }
+ // }
+ //
+ // SequenceDiagram diag = new SequenceDiagram(startTime, startTime + 20 * 5, lines, arrows);
+ // return diag;
+ // }
+
+ private void createSequenceMaps(GraphSet graphs) {
+
+ Map<GraphID, Graph> map = graphs.getMap();
+ for (Map.Entry<GraphID, Graph> entry : map.entrySet()) {
+ GraphID graphId = entry.getKey();
+ Graph graph = entry.getValue();
+ Map<String, Lifeline> lines = new LinkedHashMap<String, Lifeline>(graphs.getLocations().size());
+ List<Arrow> arrows = new ArrayList<Arrow>();
+ Map<Vertex, LifelineState> states = new HashMap<Vertex, LifelineState>();
+ for (String location : graphs.getLocations()) {
+ lines.put(location, new Lifeline(graphId, location));
+ }
+
+ Collection<Edge> edges = graph.getEdges();
+ for (Edge edge : edges) {
+ Vertex dest = edge.getDest();
+ Vertex source = edge.getSource();
+ if (dest == null) {
+ dest = source;
+ }
+ if (source == null) {
+ source = dest;
+ }
+ LifelineState destState = states.get(dest);
+ if (destState == null) {
+ final Lifeline lifeline = lines.get(dest.getName());
+ destState = createState(lifeline, graphs, dest);
+ lifeline.addState(destState);
+ states.put(dest, destState);
+ }
+ LifelineState sourceState = states.get(source);
+ if (sourceState == null) {
+ final Lifeline lifeline = lines.get(source.getName());
+ sourceState = createState(lifeline, graphs, source);
+ lifeline.addState(sourceState);
+ states.put(source, sourceState);
+ }
+ Arrow arrow = new Arrow(edge.getName(), sourceState, destState);
+ arrows.add(arrow);
+ destState.addInboundArrow(arrow);
+ }
+
+
+ lineMap.put(graphId, lines);
+ arrowMap.put(graphId, arrows);
+ }
+ }
+
+ public void showSubDiagram(GraphID id) {
+ sequenceDiagram.addSubDiagram(id, lineMap.get(id), arrowMap.get(id));
+ }
+
+ public void hideSubDiagram(GraphID id) {
+ sequenceDiagram.removeSubDiagram(id);
+ }
+
+ private SequenceDiagram createSequenceDiagram(GraphSet graphs, LineMapper lineMapper) {
+
+ sequenceDiagram = new SequenceDiagram(graphs.getMinTime(), graphs.getMaxTime(), graphs.getLocations(), lineMapper);
+ return sequenceDiagram;
+ }
+
+ private static LifelineState createState(Lifeline lifeline, GraphSet graphs, Vertex dest) {
+ long start = dest.getTimestamp();
+ long end = dest.getNextVertexOnDest() == null ? graphs.getMaxTime() : dest.getNextVertexOnDest().getTimestamp();
+ return new LifelineState(lifeline, dest.getState(), start, end);
+ }
+
+ public static void main(String[] args) throws IOException {
+ File[] files;
+ Set<String> keyFilters = new HashSet<String>();
+ boolean areGemfireLogs = false;
+ if (args.length > 0) {
+ ArrayList<File> fileList = new ArrayList<File>();
+ for (int i =0; i < args.length; i++) {
+ String arg = args[i];
+ if(arg.equals("-filterkey")) {
+ keyFilters.add(args[i+1]);
+ i++;
+ } else if(arg.equals("-logs")) {
+ areGemfireLogs = true;
+ }
+ else {
+ fileList.add(new File(args[i]));
+ }
+
+ }
+ files = fileList.toArray(new File[0]);
+ } else {
+ System.err.println("Usage: java -jar sequence.jar (-logs) (-filterkey key)* <file>+\n\n" +
+ "\t-logs (expiremental) instead of using .graph files, parse the gemfire logs to generate the sequence display" +
+ "\t-filterkey a java regular expression to match against key names. If specified\n" +
+ "The list of key sequence diagrams will only contain matching keys");
+ System.exit(1);
+ return;
+ }
+
+ final GraphSet graphs;
+
+ graphs = getGraphs(areGemfireLogs, keyFilters, files);
+
+ final LineMapper lineMapper = getLineMapper(files);
+ final GemfireSequenceDisplay display = new GemfireSequenceDisplay();
+ //Schedule a job for the event-dispatching thread:
+ //creating and showing this application's GUI.
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ display.createAndShowGUI(graphs, lineMapper);
+ }
+ });
+ }
+
+ private static GraphSet getGraphs(boolean useLogFiles, Set<String> keyFilters, File[] files)
+ throws IOException {
+ Filter graphFilter = new KeyFilter(keyFilters);
+
+
+ GraphReader reader = new GraphReader(files);
+ final GraphSet graphs;
+ if(keyFilters.isEmpty()) {
+ graphs = reader.readGraphs(useLogFiles);
+ } else {
+ graphs = reader.readGraphs(graphFilter, useLogFiles);
+ }
+ return graphs;
+ }
+
+ /**
+ * @param files
+ * @return
+ */
+ private static LineMapper getLineMapper(File[] files) {
+ if(HydraLineMapper.isInHydraRun(files)) {
+ return new HydraLineMapper(files);
+ } else {
+ return new DefaultLineMapper();
+ }
+ }
+
+ private static class KeyFilter implements Filter {
+ Set<Pattern> patterns = new HashSet<Pattern>();
+
+
+ public KeyFilter(Set<String> keyFilters) {
+ for(String filterString : keyFilters) {
+ patterns.add(Pattern.compile(filterString));
+ }
+ }
+
+ public boolean accept(GraphType graphType, String name, String edgeName,
+ String source, String dest) {
+ if(graphType.equals(GraphType.KEY)) {
+ for(Pattern pattern : patterns) {
+ if(pattern.matcher(name).find()) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public boolean acceptPattern(GraphType graphType, Pattern pattern,
+ String edgeName, String source, String dest) {
+ return true;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/HydraLineMapper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/HydraLineMapper.java b/geode-core/src/test/java/org/apache/geode/sequence/HydraLineMapper.java
new file mode 100644
index 0000000..af82c47
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/HydraLineMapper.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.geode.sequence.LineMapper;
+
+/**
+ *
+ */
+public class HydraLineMapper implements LineMapper {
+ private static final Pattern VM_NAME_PATTERN = Pattern.compile("(vm_\\d+).*_(\\d+)(_end)?\\.log");
+ private static final Pattern DISK_DIR_PATTERN = Pattern.compile("vm_(\\d+).*_disk_1");
+ private final Map<String, String> processIdToVMName = new HashMap<String, String>();
+ private final DefaultLineMapper defaultMapper = new DefaultLineMapper();
+
+ public HydraLineMapper(File[] graphFiles) {
+ File firstFile = graphFiles[0];
+ File directory = firstFile.getParentFile();
+ if(directory == null || ! new File(directory, "latest.prop").exists()) {
+ directory = new File(".");
+ }
+ String[] files = directory.list();
+ for(String file : files) {
+ Matcher matcher = VM_NAME_PATTERN.matcher(file);
+ if(matcher.matches()) {
+ processIdToVMName.put(matcher.group(2), matcher.group(1));
+ }
+ }
+
+ for(String file : files) {
+ Matcher matcher = DISK_DIR_PATTERN.matcher(file);
+ if(matcher.matches()) {
+
+ String storeId = getDiskStoreId(file);
+ if(storeId != null) {
+ processIdToVMName.put(storeId, "disk_" + matcher.group(1));
+ }
+ }
+ }
+
+
+ }
+
+ private String getDiskStoreId(String diskStoreDir) {
+ File dir = new File(diskStoreDir);
+ String[] files = dir.list();
+ for(String fileName : files) {
+ if(fileName.endsWith(".if")) {
+ try {
+ return getDiskStoreIdFromInitFile(dir, fileName);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private String getDiskStoreIdFromInitFile(File dir, String fileName)
+ throws FileNotFoundException, IOException {
+ FileInputStream fis = new FileInputStream(new File(dir, fileName));
+ try {
+ byte[] bytes = new byte[1 + 8 + 8];
+ fis.read(bytes);
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ //Skip the record type.
+ buffer.get();
+ long least = buffer.getLong();
+ long most = buffer.getLong();
+ UUID id = new UUID(most, least);
+ return id.toString();
+ } finally {
+ fis.close();
+ }
+ }
+
+ public String getShortNameForLine(String lineName) {
+ String name = defaultMapper.getShortNameForLine(lineName);
+ if(processIdToVMName.containsKey(name)) {
+ return processIdToVMName.get(name);
+ } else {
+ return name;
+ }
+ }
+
+ public static boolean isInHydraRun(File[] graphFiles) {
+ if(graphFiles.length == 0) {
+ return false;
+ }
+ File firstFile = graphFiles[0];
+ File parentFile = firstFile.getParentFile();
+ for(File file : graphFiles) {
+ if(parentFile == null && file.getParentFile() == null) {
+ return true;
+ }
+ if (parentFile == null || file.getParentFile() == null
+ || !file.getParentFile().equals(parentFile)) {
+ return false;
+ }
+ }
+
+ return new File(parentFile, "latest.prop").exists()
+ || new File("latest.prop").exists();
+
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/Lifeline.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/Lifeline.java b/geode-core/src/test/java/org/apache/geode/sequence/Lifeline.java
new file mode 100644
index 0000000..f80b533
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/Lifeline.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Oct 29, 2010
+ * Time: 3:59:02 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class Lifeline {
+ private List<LifelineState> states;
+ private final String name;
+ private final Comparable diagramName;
+ private int x;
+ private int width;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void addState(LifelineState state) {
+ this.states.add(state);
+ }
+
+ public Lifeline(Comparable diagramName, String name) {
+ this.name = name;
+ this.states = new ArrayList<LifelineState>();
+ this.diagramName = diagramName;
+ }
+
+ public void resize(int x, int lineWidth, long Ybase, double Yscale) {
+ for(LifelineState state : states) {
+ state.resize(Yscale, Ybase);
+ }
+
+ this.x = x;
+ width = lineWidth;
+ }
+
+ public void paint(Graphics2D g, StateColorMap colorMap) {
+ Rectangle boundary = g.getClipBounds();
+ if(x > boundary.getMaxX() || x + width < boundary.getMinX()) {
+ //no need to paint if this line isn't displayed
+ return;
+ }
+ //TODO - we need to clip these to the visible states
+ for(LifelineState state : states) {
+ state.paint(g, colorMap);
+ }
+ }
+
+ public List<LifelineState> getStates() {
+ return states;
+ }
+
+ public LifelineState getStateAt(int y) {
+ for(LifelineState state : states) {
+ if(state.getStartY() < y && state.getStartY() + state.getHeight() > y) {
+ return state;
+ }
+ }
+ return null;
+ }
+
+ public Comparable getDiagramName() {
+ return diagramName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/LifelineState.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/LifelineState.java b/geode-core/src/test/java/org/apache/geode/sequence/LifelineState.java
new file mode 100644
index 0000000..c1a57bf
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/LifelineState.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.JLabel;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Oct 29, 2010
+ * Time: 3:45:07 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class LifelineState {
+ private final long startTime;
+ private final long endTime;
+ private final String stateName;
+ private int startY;
+ private int height;
+ private final Lifeline line;
+ private final Set<Arrow> inboundArrows = new HashSet<Arrow>();
+ private static final int ARC_SIZE = 10;
+
+ public int getStartY() {
+ return startY;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+
+ public LifelineState(Lifeline line, String stateName, long startTime, long endTime) {
+ this.line = line;
+ this.stateName = stateName;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+
+ public void paint(Graphics2D g, StateColorMap colorMap) {
+ Rectangle bounds = g.getClipBounds();
+ if(startY > bounds.getMaxY() || startY+height <bounds.getMinY()) {
+ return;
+ }
+
+ int x = line.getX();
+ int width = line.getWidth();
+
+ Color color = colorMap.getColor(stateName);
+ g.setColor(color);
+ g.fillRoundRect(x, startY, width, height, ARC_SIZE, ARC_SIZE);
+ g.setColor(Color.BLACK);
+ }
+
+ public void highlight(Graphics2D g) {
+ Rectangle bounds = g.getClipBounds();
+ if(startY > bounds.getMaxY() || startY+height <bounds.getMinY()) {
+ return;
+ }
+
+ int x = line.getX();
+ int width = line.getWidth();
+
+ g.drawRoundRect(x, startY, width, height, ARC_SIZE, ARC_SIZE);
+ }
+
+ public void resize(double scale, long base) {
+ startY = (int) ((startTime - base) * scale);
+ height = (int) ((endTime - startTime) * scale);
+ }
+
+ public Component getPopup() {
+ return new JLabel("<html>Object: " + line.getDiagramName() + "<br>Member: " + line.getName() + "<br>State: " + stateName + "<br>Time:" + new Date(startTime) + "</html>");
+ }
+
+ public Lifeline getLine() {
+ return line;
+ }
+
+ public void addInboundArrow(Arrow arrow) {
+ inboundArrows.add(arrow);
+ }
+
+ public Set<Arrow> getInboundArrows() {
+ return inboundArrows;
+ }
+
+ @Override
+ public String toString() {
+ return line.getName() + "@" + startTime + ":" + stateName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/LineMapper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/LineMapper.java b/geode-core/src/test/java/org/apache/geode/sequence/LineMapper.java
new file mode 100644
index 0000000..91f7d6c
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/LineMapper.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+/**
+ * An interface for mapping a lifeline name to a shorter version of the same
+ * line. This could also consolodate multiple lifelines onto a single line.
+ *
+ * The most common case for this is that a lifeline represents a VM that is
+ * restarted several times. Eg time, the line name changes, but we want to put
+ * all of the states for that "logical" vm on the same line.
+ *
+ */
+public interface LineMapper {
+
+ /**
+ * Return the short name for this lifeline.
+ */
+ public String getShortNameForLine(String lineName);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/SelectGraphDialog.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/SelectGraphDialog.java b/geode-core/src/test/java/org/apache/geode/sequence/SelectGraphDialog.java
new file mode 100644
index 0000000..caa37e5
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/SelectGraphDialog.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import org.apache.geode.internal.sequencelog.model.GraphID;
+import org.apache.geode.internal.sequencelog.model.GraphSet;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Dec 9, 2010
+ * Time: 3:34:38 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SelectGraphDialog extends JDialog {
+ private List<GraphID> selectedIds = new ArrayList<GraphID>();
+ private Set<SelectionListener> listeners = new HashSet<SelectionListener>();
+
+ public SelectGraphDialog(final GraphSet graphs) {
+
+ final List<GraphID> ids = new ArrayList<GraphID>(graphs.getMap().keySet());
+ Collections.sort(ids);
+ final FilterableListModel listModel = new FilterableListModel(ids);
+ final JList list = new JList(listModel);
+
+ JScrollPane selectGraphPane = new JScrollPane(list);
+ selectGraphPane.setPreferredSize(new Dimension(500, 500));
+
+ JButton apply = new JButton("Apply");
+ apply.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ selectedIds = (List) Arrays.asList(list.getSelectedValues());
+ fireSelectionChanged();
+ setVisible(false);
+ }
+ });
+
+ JButton cancel= new JButton("Cancel");
+ cancel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ setVisible(false);
+ }
+ });
+
+ JPanel buttonPane = new JPanel();
+ buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
+ buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
+ buttonPane.add(Box.createHorizontalGlue());
+ buttonPane.add(apply);
+ buttonPane.add(cancel);
+
+ final JTextField searchField = new JTextField(10);
+ searchField.getDocument().addDocumentListener(new DocumentListener() {
+ public void removeUpdate(DocumentEvent e) {
+ doUpdate();
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ doUpdate();
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ doUpdate();
+ }
+
+ private void doUpdate() {
+ listModel.updateFilter(searchField.getText());
+ }
+ });
+
+
+ Container contentPane = getContentPane();
+ contentPane.add(searchField, BorderLayout.PAGE_START);
+ contentPane.add(selectGraphPane, BorderLayout.CENTER);
+ contentPane.add(buttonPane, BorderLayout.PAGE_END);
+ }
+
+ private void fireSelectionChanged() {
+ for(SelectionListener listener : listeners) {
+ listener.selectionChanged(selectedIds);
+ }
+ }
+
+ public void addSelectionListener(SelectionListener listener) {
+ listeners.add(listener);
+
+ }
+
+ public void removeSelectionListener(SelectionListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * A listener for changes to the graph selections
+ */
+ public static interface SelectionListener {
+ void selectionChanged(List<GraphID> selectedIds);
+ }
+
+ private static class FilterableListModel extends AbstractListModel {
+ private final List<?> allElements;
+ private List<Object> filteredElements;
+
+ public FilterableListModel(List<?> elements) {
+ this.allElements = elements;
+ this.filteredElements = new ArrayList<Object>(elements);
+ }
+
+ public int getSize() {
+ return filteredElements.size();
+ }
+
+ public Object getElementAt(int index) {
+ return filteredElements.get(index);
+ }
+
+ public void updateFilter(String filter) {
+ Pattern pattern = Pattern.compile(filter);
+ filteredElements = new ArrayList<Object>();
+ for(Object element : allElements) {
+ if(pattern.matcher(element.toString()).find()) {
+ filteredElements.add(element);
+ }
+ }
+
+ fireContentsChanged(this, 0, filteredElements.size());
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/SequenceDiagram.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/SequenceDiagram.java b/geode-core/src/test/java/org/apache/geode/sequence/SequenceDiagram.java
new file mode 100644
index 0000000..5064d8a
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/SequenceDiagram.java
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Oct 29, 2010
+ * Time: 4:18:40 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SequenceDiagram extends JPanel {
+
+ /**
+ *
+ */
+ private static final Color HIGHLIGHT_COLOR = Color.RED;
+
+ private final List<String> lineNames;
+ private final Map<String, List<String>> shortLineNames;
+ private final SortedMap<Comparable, SubDiagram> subDiagrams = new TreeMap<Comparable, SubDiagram>();
+ private final StateColorMap colorMap = new StateColorMap();
+ private final long minTime;
+ private final long maxTime;
+
+ private static int PADDING_BETWEEN_LINES = 100;
+ private static int Y_PADDING = 20;
+ private static final int STATE_WIDTH = 20;
+ private static final int LINE_LABEL_BOUNDARY = 5;
+ private static final int AXIS_SIZE=35;
+
+ private int lineStep;
+ private int lineWidth;
+ private Popup mouseover;
+ private LifelineState mouseoverState;
+ private LifelineState selectedState;
+
+ public SequenceDiagram(long minTime, long maxTime, List<String> lineNames, LineMapper lineMapper) {
+ this.lineNames = lineNames;
+ this.shortLineNames = parseShortNames(lineNames, lineMapper);
+ this.minTime = minTime;
+ this.maxTime = maxTime;
+ int width = getInitialWidth();
+ int height = 500;
+ super.setPreferredSize(new Dimension(width, height));
+ resizeMe(width, height);
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ Component source = (Component) e.getSource();
+ resizeMe(source.getWidth(), source.getHeight());
+ }
+ });
+ setBackground(Color.WHITE);
+ }
+
+ private Map<String, List<String>> parseShortNames(List<String> lineNames, LineMapper lineMapper) {
+ Map<String, List<String>> shortNames = new LinkedHashMap<String, List<String>>(lineNames.size());
+ for(String name : lineNames) {
+ String shortName = lineMapper.getShortNameForLine(name);
+ List<String> list = shortNames.get(shortName);
+ if(list == null) {
+ list = new ArrayList<String>();
+ shortNames.put(shortName, list);
+ }
+ list.add(name);
+ }
+
+ return shortNames;
+ }
+
+ public List<Comparable> getSubDiagramsNames() {
+ return new ArrayList<Comparable>(subDiagrams.keySet());
+
+ }
+
+ public void addSubDiagram(Comparable name, Map<String, Lifeline> lines, List<Arrow> arrows) {
+ subDiagrams.put(name, new SubDiagram(name, lines, arrows));
+ }
+
+ public void removeSubDiagram(Comparable name) {
+ this.subDiagrams.remove(name);
+ }
+
+ private int getInitialWidth() {
+ return (this.shortLineNames.size()) * PADDING_BETWEEN_LINES;
+ }
+
+ public void resizeMe(int width, int height) {
+ this.setPreferredSize(new Dimension(width, height));
+ float xZoom = width / (float) getInitialWidth();
+
+
+ long elapsedTime = maxTime - minTime;
+ double yScale = height / (double) elapsedTime;
+// long yBase = (long) (minTime - ((long) Y_PADDING / yScale));
+ long yBase = minTime;
+ lineStep = (int) (PADDING_BETWEEN_LINES * xZoom);
+ lineWidth = (int) (STATE_WIDTH * xZoom);
+
+ if(subDiagrams.size() <= 0) {
+ return;
+ }
+
+ int sublineWidth = lineWidth / subDiagrams.size();
+ int sublineIndex = 0;
+ for(SubDiagram diagram : subDiagrams.values()) {
+ int lineIndex = 0;
+ for(List<String> fullNames : shortLineNames.values()) {
+ for(String name : fullNames) {
+ Lifeline line = diagram.lifelines.get(name);
+ if(line != null) {
+ int lineX = lineIndex * lineStep + sublineIndex * sublineWidth;
+ line.resize(lineX, sublineWidth, yBase, yScale);
+ }
+ }
+ lineIndex++;
+ }
+ sublineIndex++;
+ }
+ }
+
+ public void showPopupText(int x, int y, int xOnScreen, int yOnScreen) {
+ LifelineState state = getStateAt(x, y);
+ if(state == mouseoverState) {
+ return;
+ }
+ if(mouseover != null) {
+ mouseover.hide();
+ }
+ if(state == null) {
+ mouseover = null;
+ mouseoverState = null;
+ } else {
+ Component popupContents = state.getPopup();
+ mouseoverState = state;
+ mouseover = PopupFactory.getSharedInstance().getPopup(this, popupContents, xOnScreen + 20, yOnScreen);
+ mouseover.show();
+ }
+ }
+
+ public void selectState(int x, int y) {
+ LifelineState state = getStateAt(x, y);
+ if(state == selectedState) {
+ return;
+ }
+
+ if(selectedState != null) {
+ fireRepaintOfDependencies(selectedState);
+ }
+
+ selectedState = state;
+
+ if(state != null) {
+ fireRepaintOfDependencies(state);
+ }
+ }
+
+ private LifelineState getStateAt(int x, int y) {
+ //TODO - this needs some
+ //serious optimization to go straight to the right state
+ // I think we need a tree map of of lines, keyed by x offset
+ //and a keymap of states keyed by y offset.
+ //That could make painting faster as well.
+ List<String> reverseList = new ArrayList<String>(lineNames);
+ Collections.reverse(reverseList);
+ for(SubDiagram diagram : subDiagrams.values()) {
+ for(String name : reverseList) {
+ Lifeline line = diagram.lifelines.get(name);
+ if(line != null) {
+ if(line.getX() < x && line.getX() + line.getWidth() > x) {
+ LifelineState state = line.getStateAt(y);
+ if(state != null) {
+ return state;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2 = (Graphics2D) g.create();
+ //TODO - we should clip these to the visible lines
+ for(SubDiagram subDiagram : subDiagrams.values()) {
+ subDiagram.paintStates(g2, colorMap);
+ }
+
+ for(SubDiagram subDiagram : subDiagrams.values()) {
+ subDiagram.paintArrows(g2, colorMap);
+ }
+ paintHighlightedComponents(g2, selectedState, new HashSet<LifelineState>());
+ }
+
+ private void fireRepaintOfDependencies(LifelineState state) {
+ //TODO - it might be more efficient to repaint just the changed
+ //areas, but right now this will do.
+ repaint();
+ }
+
+ private void paintHighlightedComponents(Graphics2D g2, LifelineState endingState, Set<LifelineState> visited) {
+ if(!visited.add(endingState)) {
+ //Prevent cycles
+ return;
+ }
+ g2.setColor(HIGHLIGHT_COLOR);
+ if(endingState != null) {
+ endingState.highlight(g2);
+
+ for(Arrow arrow : endingState.getInboundArrows()) {
+ arrow.paint(g2);
+ paintHighlightedComponents(g2, arrow.getStartingState(), visited);
+ }
+ }
+
+
+ }
+
+ public long getMinTime() {
+ return minTime;
+ }
+
+ public long getMaxTime() {
+ return maxTime;
+ }
+
+ public JComponent createMemberAxis() {
+ return new MemberAxis();
+ }
+
+ private class MemberAxis extends JComponent {
+ public MemberAxis() {
+ setPreferredSize(new Dimension(getWidth(), AXIS_SIZE));
+ SequenceDiagram.this.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ int newWidth = e.getComponent().getWidth();
+ setPreferredSize(new Dimension(newWidth, AXIS_SIZE));
+ revalidate();
+ }
+ });
+ }
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Rectangle bounds = g.getClipBounds();
+ int index = 0;
+ for(String name : shortLineNames.keySet()) {
+ int nameWidth = g.getFontMetrics().stringWidth(name);
+ int lineX = lineStep * index;
+ index++;
+ if(bounds.getMaxX() < lineX
+ || bounds.getMinX() > lineX + nameWidth) {
+ continue;
+ }
+ g.setClip(lineX + LINE_LABEL_BOUNDARY, 0, lineStep - + LINE_LABEL_BOUNDARY * 2, getHeight());
+ g.drawString(name, lineX + LINE_LABEL_BOUNDARY, AXIS_SIZE / 3);
+ g.setClip(null);
+ }
+ }
+ }
+
+ public static class SubDiagram {
+ private final Map<String, Lifeline> lifelines;
+ private final List<Arrow> arrows;
+ private final Comparable name;
+
+ public SubDiagram(Comparable name, Map<String, Lifeline> lines, List<Arrow> arrows) {
+ this.name = name;
+ this.lifelines = lines;
+ this.arrows = arrows;
+ }
+
+ public void paintStates(Graphics2D g2, StateColorMap colorMap) {
+ for(Lifeline line: lifelines.values()) {
+ line.paint(g2, colorMap);
+ }
+ }
+ public void paintArrows(Graphics2D g2, StateColorMap colorMap) {
+ Color lineColor = colorMap.getColor(name);
+ g2.setColor(lineColor);
+ for(Arrow arrow: arrows) {
+ arrow.paint(g2);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/SequencePanel.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/SequencePanel.java b/geode-core/src/test/java/org/apache/geode/sequence/SequencePanel.java
new file mode 100644
index 0000000..daefc08
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/SequencePanel.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dan
+ * Date: Oct 28, 2010
+ * Time: 10:29:23 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SequencePanel extends JPanel {
+
+ public SequencePanel(SequenceDiagram sequenceDiagram) {
+ //Set up the drawing area.
+ ZoomingPanel drawingPane = new ZoomingPanel();
+ drawingPane.setBackground(Color.white);
+ drawingPane.setSequenceDiagram(sequenceDiagram);
+
+ //Put the drawing area in a scroll pane.
+ final JScrollPane scroller = new JScrollPane(drawingPane);
+ scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ final TimeAxis timeAxis = new TimeAxis(TimeAxis.VERTICAL,
+ sequenceDiagram.getMinTime(),
+ sequenceDiagram.getMaxTime());
+ timeAxis.setPreferredHeight(drawingPane.getHeight());
+ scroller.setRowHeaderView(timeAxis);
+ scroller.setColumnHeaderView(sequenceDiagram.createMemberAxis());
+ int preferredWidth = (int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() - 100);
+ int preferredHeight = (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() - 100);
+ scroller.setPreferredSize(new Dimension(preferredWidth, preferredHeight));
+ scroller.setAutoscrolls(true);
+// scroller.setPreferredSize(new Dimension(200,200));
+
+ sequenceDiagram.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ int height = e.getComponent().getHeight();
+ timeAxis.setPreferredHeight(height);
+ timeAxis.revalidate();
+ }
+ });
+
+ BorderLayout layout = new BorderLayout();
+// layout.setHgap(0);
+// layout.setVgap(0);
+ setLayout(layout);
+ //Lay out this demo.
+// add(instructionPanel, BorderLayout.PAGE_START);
+ add(scroller, BorderLayout.CENTER);
+
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ Component source =e.getComponent();
+ scroller.setSize(source.getSize());
+ scroller.revalidate();
+ }
+ });
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/StateColorMap.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/StateColorMap.java b/geode-core/src/test/java/org/apache/geode/sequence/StateColorMap.java
new file mode 100644
index 0000000..0ef3ab7
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/StateColorMap.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import java.awt.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.lang.Math.random;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Nov 12, 2010
+ * Time: 5:05:49 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class StateColorMap {
+ private Map<Object, Color> colors = new HashMap<Object, Color>();
+ private static Color[] PREDEFINED_COLORS = new Color[] { Color.BLUE, Color.BLACK, Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN};
+
+ private ColorList colorList = new ColorList();
+
+ public StateColorMap() {
+ colors.put("created", Color.GREEN);
+ colors.put("destroyed", Color.WHITE);
+ colors.put("persisted", new Color(0, 150, 0));
+ }
+
+
+ public Color getColor(Object state) {
+ Color color = colors.get(state);
+ if(color == null) {
+ color = colorList.nextColor();
+ colors.put(state, color);
+ }
+
+ return color;
+ }
+
+ private static class ColorList {
+ int colorIndex;
+
+ public Color nextColor() {
+ if(colorIndex < PREDEFINED_COLORS.length) {
+ return PREDEFINED_COLORS[colorIndex++];
+ } else {
+ return Color.getHSBColor((float)random(), (float)random(), (float)random());
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/TimeAxis.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/TimeAxis.java b/geode-core/src/test/java/org/apache/geode/sequence/TimeAxis.java
new file mode 100644
index 0000000..39d14ff
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/TimeAxis.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import javax.swing.*;
+import java.awt.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dsmith
+ * Date: Oct 29, 2010
+ * Time: 5:24:54 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class TimeAxis extends JComponent {
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+ public static final int SIZE = 100;
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS");
+
+ public int orientation;
+ private long minTime;
+ private long maxTime;
+
+ public TimeAxis(int orientation, long minTime, long maxTime) {
+ this.orientation = orientation;
+ this.minTime = minTime;
+ this.maxTime = maxTime;
+ }
+
+ public void setPreferredHeight(int ph) {
+ setPreferredSize(new Dimension(SIZE, ph));
+ }
+
+ public void setPreferredWidth(int pw) {
+ setPreferredSize(new Dimension(pw, SIZE));
+ }
+
+ protected void paintComponent(Graphics g) {
+ Rectangle drawHere = g.getClipBounds();
+
+ int height = getHeight();
+
+ double scale = (maxTime - minTime) / height;
+ int increment = 30;
+ // Fill clipping area with dirty brown/orange.
+ g.setColor(new Color(230, 163, 4));
+ g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);
+
+ // Do the ruler labels in a small font that's black.
+ g.setFont(new Font("SansSerif", Font.PLAIN, 10));
+ g.setColor(Color.black);
+
+ // Some vars we need.
+ int end = 0;
+ int start = 0;
+ int tickLength = 0;
+ String text = null;
+
+ // Use clipping bounds to calculate first and last tick locations.
+ if (orientation == HORIZONTAL) {
+ start = (drawHere.x / increment) * increment;
+ end = (((drawHere.x + drawHere.width) / increment) + 1)
+ * increment;
+ } else {
+ start = (drawHere.y / increment) * increment;
+ end = (((drawHere.y + drawHere.height) / increment) + 1)
+ * increment;
+ }
+
+ // Make a special case of 0 to display the number
+ // within the rule and draw a units label.
+ if (start == 0) {
+ text = DATE_FORMAT.format(new Date(minTime));
+ tickLength = 10;
+ if (orientation == HORIZONTAL) {
+ g.drawLine(0, SIZE-1, 0, SIZE-tickLength-1);
+ g.drawString(text, 2, 21);
+ } else {
+ g.drawLine(SIZE-1, 0, SIZE-tickLength-1, 0);
+ g.drawString(text, 9, 10);
+ }
+ text = null;
+ start = increment;
+ }
+
+ // ticks and labels
+ for (int i = start; i < end; i += increment) {
+ tickLength = 10;
+ text = DATE_FORMAT.format(new Date((long) (minTime + i * scale)));
+
+ if (tickLength != 0) {
+ if (orientation == HORIZONTAL) {
+ g.drawLine(i, SIZE-1, i, SIZE-tickLength-1);
+ if (text != null)
+ g.drawString(text, i-3, 21);
+ } else {
+ g.drawLine(SIZE-1, i, SIZE-tickLength-1, i);
+ if (text != null)
+ g.drawString(text, 9, i+3);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/geode/sequence/ZoomingPanel.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/sequence/ZoomingPanel.java b/geode-core/src/test/java/org/apache/geode/sequence/ZoomingPanel.java
new file mode 100644
index 0000000..09f6ef6
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/sequence/ZoomingPanel.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.sequence;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dan
+ * Date: Oct 28, 2010
+ * Time: 10:30:40 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ZoomingPanel extends JPanel {
+ private int zoomBoxStartX;
+ private int zoomBoxStartY;
+ private int zoomBoxWidth;
+ private int zoomBoxHeight;
+ private SequenceDiagram child;
+
+
+ public ZoomingPanel() {
+ super();
+ addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ startBox(e.getX(), e.getY());
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ endBox(e.getX(), e.getY());
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getButton() != MouseEvent.BUTTON1) {
+ unzoom();
+ } else {
+ child.selectState(e.getX(), e.getY());
+ }
+
+ }
+ });
+
+ addMouseMotionListener(new MouseMotionAdapter() {
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
+ ((JPanel)e.getSource()).scrollRectToVisible(r);
+ showBox(e.getX(), e.getY());
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ int popupX = ZoomingPanel.this.getLocationOnScreen().x + e.getX();
+ int popupY = ZoomingPanel.this.getLocationOnScreen().y + e.getY();
+ child.showPopupText(e.getX(), e.getY(), popupX, popupY);
+ }
+ });
+ BorderLayout layout = new BorderLayout();
+ layout.setHgap(0);
+ layout.setVgap(0);
+ this.setLayout(layout);
+ }
+
+ private void unzoom() {
+ resizeMe(0, 0, getWidth(), getHeight());
+ }
+
+ void resizeMe(int zoomBoxX, int zoomBoxY, int zoomBoxWidth, int zoomBoxHeight) {
+ Dimension viewSize = getParent().getSize();
+ double windowWidth = viewSize.getWidth();
+ double windowHeight = viewSize.getHeight();
+ double scaleX = getWidth() / ((double) zoomBoxWidth);
+ double scaleY = getHeight() / ((double) zoomBoxHeight);
+ int oldWidth = getWidth();
+ int oldHeight = getHeight();
+ int width = (int) (scaleX * windowWidth);
+ int height = (int) (scaleY * windowHeight);
+// this.setPreferredSize(new Dimension(width, height));
+ child.resizeMe(width, height);
+ //TODO not sure this one is needed
+ this.revalidate();
+
+ //scroll to the new rectangle
+// int scrollX = (int) (zoomBoxX * scaleX);
+// int scrollY = (int) (zoomBoxY * scaleY);
+// int scrollWidth= (int) (zoomBoxWidth * scaleX);
+// int scrollHeight = (int) (zoomBoxHeight * scaleY);
+ int scrollX = (int) (zoomBoxX * (width / (double) oldWidth));
+ int scrollY = (int) (zoomBoxY * (height / (double) oldHeight));
+ int scrollWidth= (int) (zoomBoxWidth * (width / (double) oldWidth));
+ int scrollHeight = (int) (zoomBoxHeight * (height / (double) oldHeight));
+ Rectangle r = new Rectangle(scrollX, scrollY, scrollWidth, scrollHeight);
+ ((JViewport)getParent()).scrollRectToVisible(r);
+ repaint();
+
+ }
+
+ public void setSequenceDiagram(SequenceDiagram diag) {
+ this.child = diag;
+ this.add(child, BorderLayout.CENTER);
+ }
+
+ private void showBox(int x, int y) {
+ if(zoomBoxWidth != -1) {
+ repaint(getBoxX(), getBoxY(), getBoxWidth(), getBoxHeight());
+ }
+
+ this.zoomBoxWidth = x - zoomBoxStartX;
+ this.zoomBoxHeight = y - zoomBoxStartY;
+
+ repaint(getBoxX(), getBoxY(), getBoxWidth(), getBoxHeight());
+ }
+
+ private void startBox(int x, int y) {
+ this.zoomBoxStartX = x;
+ this.zoomBoxStartY = y;
+ }
+
+ private void endBox(int x, int y) {
+ if(zoomBoxStartX != -1 && zoomBoxStartY != -1
+ && zoomBoxWidth != -1 && zoomBoxHeight != -1
+ && zoomBoxWidth != 0 && zoomBoxHeight != 0) {
+ resizeMe(getBoxX() , getBoxY(), getBoxWidth(), getBoxHeight());
+ repaint(getBoxX(), getBoxY(), getBoxWidth(), getBoxHeight());
+ this.zoomBoxStartX = -1;
+ this.zoomBoxStartY = -1;
+ this.zoomBoxWidth = -1;
+ this.zoomBoxHeight = -1;
+ }
+ }
+
+ public int getBoxX() {
+ return zoomBoxWidth >= 0 ? zoomBoxStartX : zoomBoxStartX + zoomBoxWidth;
+ }
+
+ public int getBoxY() {
+ return zoomBoxHeight >= 0 ? zoomBoxStartY : zoomBoxStartY + zoomBoxHeight;
+ }
+
+ public int getBoxHeight() {
+ return zoomBoxHeight >= 0 ? zoomBoxHeight : -zoomBoxHeight;
+ }
+
+ public int getBoxWidth() {
+ return zoomBoxWidth >= 0 ? zoomBoxWidth : -zoomBoxWidth;
+ }
+
+
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ if(zoomBoxStartX != -1 && zoomBoxStartY != -1 && zoomBoxWidth != -1 && zoomBoxHeight != -1) {
+ Graphics2D g2 = (Graphics2D) g.create();
+
+ Composite old = g2.getComposite();
+ g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
+ g2.setColor(Color.BLUE);
+
+// g2.drawRect(zoomBoxStartX, zoomBoxStartY, zoomBoxWidth, zoomBoxHeight);
+// g2.setBackground(Color.BLUE);
+ g2.fillRect(getBoxX(), getBoxY(), getBoxWidth(), getBoxHeight());
+ g2.setComposite(old);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/sequence/Arrow.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/sequence/Arrow.java b/geode-core/src/test/java/org/apache/sequence/Arrow.java
deleted file mode 100644
index 4274aa9..0000000
--- a/geode-core/src/test/java/org/apache/sequence/Arrow.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sequence;
-
-import java.awt.*;
-import java.awt.geom.GeneralPath;
-
-/**
- * Created by IntelliJ IDEA.
- * User: dsmith
- * Date: Nov 12, 2010
- * Time: 12:02:20 PM
- * To change this template use File | Settings | File Templates.
- */
-public class Arrow {
- private static int ARROW_WIDTH=10;
- private static int CIRCLE_WIDTH=6;
- private static int LABEL_OFFSET=10;
-
- private final String label;
- private final LifelineState startingState;
- private final LifelineState endingState;
-
- public Arrow(String label, LifelineState startingState, LifelineState endingState) {
- this.label = label;
- this.startingState = startingState;
- this.endingState = endingState;
- }
-
-
- public void paint(Graphics2D g) {
- Rectangle boundary = g.getClipBounds();
- int y = endingState.getStartY();
-
- //don't paint if we're not in the clip area
- if(y + ARROW_WIDTH < boundary.getMinY() || y - ARROW_WIDTH > boundary.getMaxY()) {
- return;
- }
-
- //TODO - we need to clip by X coordinate as well.
-
- boolean isReflexsive = getStartingLine() == getEndingLine();
- if(isReflexsive) {
- paintReflexive(g);
- } else {
- paintNormal(g);
- }
- }
-
- private Lifeline getStartingLine() {
- return startingState.getLine();
- }
-
- private Lifeline getEndingLine() {
- return endingState.getLine();
- }
-
- private void paintReflexive(Graphics2D g) {
- Lifeline startingLine = getStartingLine();
- int x = startingLine.getX();
- int y = endingState.getStartY();
-
- g.drawArc(x + startingLine.getWidth() - ARROW_WIDTH / 2, y - ARROW_WIDTH, ARROW_WIDTH, ARROW_WIDTH, 90, -180);
- g.drawString(label, x + startingLine.getWidth() + LABEL_OFFSET, y);
-// GeneralPath path = new GeneralPath();
-// path.moveTo(x, y - ARROW_WIDTH);
-// path.quadTo(x, y - ARROW_WIDTH);
- }
-
- private void paintNormal(Graphics2D g) {
- Lifeline startingLine = getStartingLine();
- Lifeline endingLine = getEndingLine();
- int x1 = startingLine.getX();
- int x2 = endingLine.getX();
- int y = endingState.getStartY();
-
- if(x2 > x1) {
- int startX = x1 + startingLine.getWidth();
- int endX = x2;
-
- GeneralPath path = new GeneralPath();
- path.moveTo(startX, y);
- path.lineTo(endX, y);
- path.lineTo(endX - ARROW_WIDTH, y - ARROW_WIDTH);
- path.moveTo(endX, y);
- path.lineTo(endX - ARROW_WIDTH, y + ARROW_WIDTH);
- g.draw(path);
- g.fillArc(startX, y - CIRCLE_WIDTH/2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360);
- g.drawString(label, startX + LABEL_OFFSET, y - LABEL_OFFSET);
- } else {
- int startX = x1;
- int endX = x2 + endingLine.getWidth();
-
- GeneralPath path = new GeneralPath();
- path.moveTo(startX, y);
- path.lineTo(endX, y);
- path.lineTo(endX + ARROW_WIDTH, y - ARROW_WIDTH);
- path.moveTo(endX, y);
- path.lineTo(endX + ARROW_WIDTH, y + ARROW_WIDTH);
- g.draw(path);
- int labelWidth = g.getFontMetrics().stringWidth(label);
- g.fillArc(startX - CIRCLE_WIDTH/2, y - CIRCLE_WIDTH/2, CIRCLE_WIDTH, CIRCLE_WIDTH, 0, 360);
- g.drawString(label, startX - LABEL_OFFSET - labelWidth, y - LABEL_OFFSET);
- }
- }
-
- public LifelineState getStartingState() {
- return startingState;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/sequence/Lifeline.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/sequence/Lifeline.java b/geode-core/src/test/java/org/apache/sequence/Lifeline.java
deleted file mode 100644
index f5de6ac..0000000
--- a/geode-core/src/test/java/org/apache/sequence/Lifeline.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sequence;
-
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Created by IntelliJ IDEA.
- * User: dsmith
- * Date: Oct 29, 2010
- * Time: 3:59:02 PM
- * To change this template use File | Settings | File Templates.
- */
-public class Lifeline {
- private List<LifelineState> states;
- private final String name;
- private final Comparable diagramName;
- private int x;
- private int width;
-
- public String getName() {
- return name;
- }
-
- public int getX() {
- return x;
- }
-
- public int getWidth() {
- return width;
- }
-
- public void addState(LifelineState state) {
- this.states.add(state);
- }
-
- public Lifeline(Comparable diagramName, String name) {
- this.name = name;
- this.states = new ArrayList<LifelineState>();
- this.diagramName = diagramName;
- }
-
- public void resize(int x, int lineWidth, long Ybase, double Yscale) {
- for(LifelineState state : states) {
- state.resize(Yscale, Ybase);
- }
-
- this.x = x;
- width = lineWidth;
- }
-
- public void paint(Graphics2D g, StateColorMap colorMap) {
- Rectangle boundary = g.getClipBounds();
- if(x > boundary.getMaxX() || x + width < boundary.getMinX()) {
- //no need to paint if this line isn't displayed
- return;
- }
- //TODO - we need to clip these to the visible states
- for(LifelineState state : states) {
- state.paint(g, colorMap);
- }
- }
-
- public List<LifelineState> getStates() {
- return states;
- }
-
- public LifelineState getStateAt(int y) {
- for(LifelineState state : states) {
- if(state.getStartY() < y && state.getStartY() + state.getHeight() > y) {
- return state;
- }
- }
- return null;
- }
-
- public Comparable getDiagramName() {
- return diagramName;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/sequence/LifelineState.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/sequence/LifelineState.java b/geode-core/src/test/java/org/apache/sequence/LifelineState.java
deleted file mode 100644
index 2f39c46..0000000
--- a/geode-core/src/test/java/org/apache/sequence/LifelineState.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sequence;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.swing.JLabel;
-
-/**
- * Created by IntelliJ IDEA.
- * User: dsmith
- * Date: Oct 29, 2010
- * Time: 3:45:07 PM
- * To change this template use File | Settings | File Templates.
- */
-public class LifelineState {
- private final long startTime;
- private final long endTime;
- private final String stateName;
- private int startY;
- private int height;
- private final Lifeline line;
- private final Set<Arrow> inboundArrows = new HashSet<Arrow>();
- private static final int ARC_SIZE = 10;
-
- public int getStartY() {
- return startY;
- }
-
- public int getHeight() {
- return height;
- }
-
-
- public LifelineState(Lifeline line, String stateName, long startTime, long endTime) {
- this.line = line;
- this.stateName = stateName;
- this.startTime = startTime;
- this.endTime = endTime;
- }
-
- public void paint(Graphics2D g, StateColorMap colorMap) {
- Rectangle bounds = g.getClipBounds();
- if(startY > bounds.getMaxY() || startY+height <bounds.getMinY()) {
- return;
- }
-
- int x = line.getX();
- int width = line.getWidth();
-
- Color color = colorMap.getColor(stateName);
- g.setColor(color);
- g.fillRoundRect(x, startY, width, height, ARC_SIZE, ARC_SIZE);
- g.setColor(Color.BLACK);
- }
-
- public void highlight(Graphics2D g) {
- Rectangle bounds = g.getClipBounds();
- if(startY > bounds.getMaxY() || startY+height <bounds.getMinY()) {
- return;
- }
-
- int x = line.getX();
- int width = line.getWidth();
-
- g.drawRoundRect(x, startY, width, height, ARC_SIZE, ARC_SIZE);
- }
-
- public void resize(double scale, long base) {
- startY = (int) ((startTime - base) * scale);
- height = (int) ((endTime - startTime) * scale);
- }
-
- public Component getPopup() {
- return new JLabel("<html>Object: " + line.getDiagramName() + "<br>Member: " + line.getName() + "<br>State: " + stateName + "<br>Time:" + new Date(startTime) + "</html>");
- }
-
- public Lifeline getLine() {
- return line;
- }
-
- public void addInboundArrow(Arrow arrow) {
- inboundArrows.add(arrow);
- }
-
- public Set<Arrow> getInboundArrows() {
- return inboundArrows;
- }
-
- @Override
- public String toString() {
- return line.getName() + "@" + startTime + ":" + stateName;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ba853da/geode-core/src/test/java/org/apache/sequence/LineMapper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/sequence/LineMapper.java b/geode-core/src/test/java/org/apache/sequence/LineMapper.java
deleted file mode 100644
index d9c7e08..0000000
--- a/geode-core/src/test/java/org/apache/sequence/LineMapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sequence;
-
-/**
- * An interface for mapping a lifeline name to a shorter version of the same
- * line. This could also consolodate multiple lifelines onto a single line.
- *
- * The most common case for this is that a lifeline represents a VM that is
- * restarted several times. Eg time, the line name changes, but we want to put
- * all of the states for that "logical" vm on the same line.
- *
- */
-public interface LineMapper {
-
- /**
- * Return the short name for this lifeline.
- */
- public String getShortNameForLine(String lineName);
-
-}