/** * Copyright Plugtree LLC * * Licensed 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 com.plugtree.solrmeter.view.statistic; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collections; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.swing.SwingUtilities; import org.apache.log4j.Logger; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.DefaultXYDataset; import org.jfree.ui.RectangleEdge; import com.google.inject.Inject; import com.plugtree.stressTestScope.StressTestScope; import com.plugtree.solrmeter.model.statistic.OperationTimeHistory; import com.plugtree.solrmeter.view.I18n; import com.plugtree.solrmeter.view.StatisticPanel; @StressTestScope public class OperationTimeLineChartPanel extends StatisticPanel implements ActionListener { private static final long serialVersionUID = 3661614439597184136L; private static final String SERIES_KEY_COMMIT_TIME = "commitTime"; private static final String SERIES_KEY_QUERIES_TIME = "queriesTime"; private static final String SERIES_KEY_UPDATES_TIME = "updatesTime"; private static final String SERIES_KEY_OPTIMIZE_TIME = "optimizeTime"; private static final Logger logger = Logger.getLogger(OperationTimeLineChartPanel.class); private DefaultXYDataset xyDataset = new DefaultXYDataset(); private OperationTimeHistory statistic; private JCheckBox checkBoxShowQueries; private JCheckBox checkBoxShowOptimize; private JCheckBox checkBoxShowAdd; private JCheckBox checkBoxShowCommit; @Inject public OperationTimeLineChartPanel(OperationTimeHistory statistic) { super(); this.statistic = statistic; this.xyDataset = new DefaultXYDataset(); this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); this.add(this.createChartPanel()); this.add(this.createCheckBoxPanel()); } private Component createCheckBoxPanel() { JPanel panelCheckBox = new JPanel(); panelCheckBox.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); panelCheckBox.setLayout(new BoxLayout(panelCheckBox, BoxLayout.X_AXIS)); checkBoxShowCommit = new JCheckBox(I18n.get("statistic.operationTimeLineChartPanel.checkbox.commit")); checkBoxShowCommit.addActionListener(this); checkBoxShowOptimize = new JCheckBox(I18n.get("statistic.operationTimeLineChartPanel.checkbox.optimize")); checkBoxShowOptimize.addActionListener(this); checkBoxShowAdd = new JCheckBox(I18n.get("statistic.operationTimeLineChartPanel.checkbox.add")); checkBoxShowAdd.addActionListener(this); checkBoxShowQueries = new JCheckBox(I18n.get("statistic.operationTimeLineChartPanel.checkbox.query")); checkBoxShowQueries.addActionListener(this); panelCheckBox.add(Box.createHorizontalGlue()); panelCheckBox.add(checkBoxShowCommit); panelCheckBox.add(Box.createHorizontalGlue()); panelCheckBox.add(checkBoxShowOptimize); panelCheckBox.add(Box.createHorizontalGlue()); panelCheckBox.add(checkBoxShowQueries); panelCheckBox.add(Box.createHorizontalGlue()); panelCheckBox.add(checkBoxShowAdd); panelCheckBox.add(Box.createHorizontalGlue()); panelCheckBox.setMaximumSize(new Dimension(800, 25)); checkAll(); return panelCheckBox; } private Component createChartPanel() { NumberAxis xaxis = new NumberAxis(I18n.get("statistic.operationTimeLineChartPanel.executionInstant")); NumberAxis yaxis = new NumberAxis(I18n.get("statistic.operationTimeLineChartPanel.qTime")); XYPlot plot = new XYPlot(xyDataset, xaxis, yaxis, new XYLineAndShapeRenderer(true, true)); JFreeChart chart = new JFreeChart(I18n.get("statistic.operationTimeLineChartPanel.title"), null, plot, true); chart.getLegend().setPosition(RectangleEdge.RIGHT); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(CHART_BORDER); chartPanel.setMinimumDrawHeight(0); chartPanel.setMinimumDrawWidth(0); chartPanel.setMaximumDrawHeight(Integer.MAX_VALUE); chartPanel.setMaximumDrawWidth(Integer.MAX_VALUE); return chartPanel; } private void checkAll() { checkBoxShowCommit.setSelected(true); checkBoxShowOptimize.setSelected(true); checkBoxShowAdd.setSelected(true); checkBoxShowQueries.setSelected(true); } @Override public String getStatisticName() { return I18n.get("statistic.operationTimeLineChartPanel.title"); } @Override public synchronized void refreshView() { logger.debug("refreshing Time Line"); // instead of deleting the series when a checkbox is unchecked, // I prefer to use an empty map because in this way the legend // and colors of the chart remain unchanged Map<Long,Long> emptyMap = Collections.emptyMap(); if(checkBoxShowCommit.isSelected()) { refreshSeries(statistic.getCommitTime(), SERIES_KEY_COMMIT_TIME); } else { refreshSeries(emptyMap, SERIES_KEY_COMMIT_TIME); } if(checkBoxShowQueries.isSelected()) { refreshSeries(statistic.getQueriesTime(), SERIES_KEY_QUERIES_TIME); } else { refreshSeries(emptyMap, SERIES_KEY_QUERIES_TIME); } if(checkBoxShowAdd.isSelected()) { refreshSeries(statistic.getUpdatesTime(), SERIES_KEY_UPDATES_TIME); } else { refreshSeries(emptyMap, SERIES_KEY_UPDATES_TIME); } if(checkBoxShowOptimize.isSelected()) { refreshSeries(statistic.getOptimizeTime(), SERIES_KEY_OPTIMIZE_TIME); } else { refreshSeries(emptyMap, SERIES_KEY_OPTIMIZE_TIME); } } private void refreshSeries(Map<Long, Long> data, Comparable<?> seriesKey) { int i = 0; double[][] seriesData; synchronized(data) { seriesData = new double[2][data.size()]; for(Map.Entry<Long, Long> xy: data.entrySet()) { seriesData[0][i] = xy.getKey()/1000.0; seriesData[1][i] = xy.getValue(); i++; } } xyDataset.addSeries(seriesKey, seriesData); } @Override public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { refreshView(); } }); } }