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 <hkhame...@pivotal.io> Authored: Mon Sep 19 13:45:10 2016 -0700 Committer: Hitesh Khamesra <hkhame...@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); - -}