diff options
Diffstat (limited to 'java/perftests/visualisation-jfc/src/main/java/org')
27 files changed, 885 insertions, 172 deletions
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java index ed09f4a77e..5a77f22148 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java @@ -21,5 +21,5 @@ package org.apache.qpid.disttest.charting; public enum ChartType { - LINE, LINE3D, BAR, BAR3D, XYLINE, STATISTICAL_BAR + LINE, LINE3D, BAR, BAR3D, XYLINE, TIMELINE, STATISTICAL_BAR } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java index e00859855e..91eafe324b 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java @@ -30,7 +30,8 @@ import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilder; import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilderFactory; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator; -import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcUrlGenerator; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; import org.apache.qpid.disttest.charting.writer.ChartWriter; import org.jfree.chart.JFreeChart; @@ -44,24 +45,46 @@ import org.slf4j.LoggerFactory; * The following arguments are understood: * </p> * <ol> - * <li>chart-defs=<i>directory contain chartdef file(s)</i></li> - * <li>output-dir=<i>directory in which to produce the PNGs</i></li> + * <li>{@link #OUTPUT_DIR_PROP}</li> + * <li>{@link #CHART_DEFINITIONS_PROP}</li> + * <li>{@link #SUMMARY_TITLE_PROP}</li> + * <li>{@link #JDBC_DRIVER_NAME_PROP}</li> + * <li>{@link #JDBC_URL_PROP}</li> * </ol> + * Default values are indicated by the similarly named constants in this class. */ public class ChartingUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ChartingUtil.class); + /** directory in which to produce the PNGs */ public static final String OUTPUT_DIR_PROP = "outputdir"; public static final String OUTPUT_DIR_DEFAULT = "."; + /** the path to the directory containing the chart definition files */ public static final String CHART_DEFINITIONS_PROP = "chart-defs"; public static final String CHART_DEFINITIONS_DEFAULT = "."; + public static final String SUMMARY_TITLE_PROP = "summary-title"; + public static final String SUMMARY_TITLE_DEFAULT = "Performance Charts"; + + /** the class name of the JDBC driver to use for reading the chart data */ + public static final String JDBC_DRIVER_NAME_PROP = "jdbcDriverClass"; + public static final String JDBC_DRIVER_NAME_DEFAULT = JdbcUrlGenerator.DEFAULT_JDBC_DRIVER_NAME; + + /** the JDBC URL of the data to be charted */ + public static final String JDBC_URL_PROP = "jdbcUrl"; + public static final String JDBC_URL_DEFAULT = null; + + private Map<String,String> _cliOptions = new HashMap<String, String>(); + { _cliOptions.put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); _cliOptions.put(CHART_DEFINITIONS_PROP, CHART_DEFINITIONS_DEFAULT); + _cliOptions.put(SUMMARY_TITLE_PROP, SUMMARY_TITLE_DEFAULT); + _cliOptions.put(JDBC_DRIVER_NAME_PROP, JDBC_DRIVER_NAME_DEFAULT); + _cliOptions.put(JDBC_URL_PROP, JDBC_URL_DEFAULT); } public static void main(String[] args) throws Exception @@ -82,26 +105,38 @@ public class ChartingUtil private void produceAllCharts() { - final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); - final File chartDirectory = new File(_cliOptions.get(OUTPUT_DIR_PROP)); - LOGGER.info("Chart chartdef directory/file: {} output directory : {}", chartingDefsDir, chartDirectory); - - List<ChartingDefinition> definitions = loadChartDefinitions(chartingDefsDir); - - LOGGER.info("There are {} chart(s) to produce", definitions.size()); final ChartWriter writer = new ChartWriter(); - writer.setOutputDirectory(chartDirectory); + writer.setOutputDirectory(new File(_cliOptions.get(OUTPUT_DIR_PROP))); + + SeriesBuilder seriesBuilder = new JdbcSeriesBuilder( + _cliOptions.get(JDBC_DRIVER_NAME_PROP), + _cliOptions.get(JDBC_URL_PROP)); - final SeriesBuilder seriesBuilder = new JdbcCsvSeriesBuilder(); - for (ChartingDefinition chartingDefinition : definitions) + for (ChartingDefinition chartingDefinition : loadChartDefinitions()) { - ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType(), seriesBuilder); + ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder( + chartingDefinition.getChartType(), + seriesBuilder); + JFreeChart chart = chartBuilder.buildChart(chartingDefinition); - writer.writeChartToFileSystem(chart, chartingDefinition.getChartStemName()); + writer.writeChartToFileSystem(chart, chartingDefinition); } - writer.writeHtmlSummaryToFileSystem(); + final String summaryChartTitle = _cliOptions.get(SUMMARY_TITLE_PROP); + writer.writeHtmlSummaryToFileSystem(summaryChartTitle); + } + + private List<ChartingDefinition> loadChartDefinitions() + { + final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); + + LOGGER.info("Chart chartdef directory/file: {}", chartingDefsDir); + + List<ChartingDefinition> definitions = loadChartDefinitions(chartingDefsDir); + + LOGGER.info("There are {} chart(s) to produce", definitions.size()); + return definitions; } private List<ChartingDefinition> loadChartDefinitions(String chartingDefsDir) diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java index 491bb1c67d..b10fd477ed 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java @@ -36,7 +36,7 @@ public class BarChart3DBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java index b5c6a38067..7705ef5d3a 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java @@ -35,7 +35,7 @@ public class BarChartBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java index def87f5840..9cadf0ec3c 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java @@ -23,6 +23,9 @@ import java.awt.Color; import java.awt.GradientPaint; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.title.ShortTextTitle; @@ -30,12 +33,67 @@ import org.jfree.data.general.Dataset; public abstract class BaseChartBuilder implements ChartBuilder { - private static final GradientPaint BLUE_GRADIENT = new GradientPaint(0, 0, Color.white, 0, 1000, Color.blue); + static final GradientPaint BLUE_GRADIENT = new GradientPaint(0, 0, Color.white, 0, 1000, Color.blue); - public void addCommonChartAttributes(JFreeChart chart, ChartingDefinition chartingDefinition) + private SeriesPainter _seriesPainter = new SeriesPainter(); + + private final SeriesBuilder _seriesBuilder; + + protected BaseChartBuilder(SeriesBuilder seriesBuilder) + { + _seriesBuilder = seriesBuilder; + } + + @Override + public JFreeChart buildChart(ChartingDefinition chartingDefinition) + { + _seriesBuilder.setDatasetHolder(newDatasetHolder()); + Dataset dataset = _seriesBuilder.build(chartingDefinition.getSeriesDefinitions()); + + JFreeChart chart = createChart(chartingDefinition, dataset); + return chart; + } + + + /** + * return a holder of an empty dataset suitable for use with the chart type + * returned by {@link #createChartImpl(String, String, String, Dataset, PlotOrientation, boolean, boolean, boolean)}. + */ + protected abstract DatasetHolder newDatasetHolder(); + + /** + * Create a chart with the supplied parameters. + * + * For ease of implementation, the signature is intentionally similar + * to {@link ChartFactory}'s factory methods. + */ + protected abstract JFreeChart createChartImpl( + String title, String xAxisTitle, String yAxisTitle, + final Dataset dataset, + PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls); + + /** + * Create a {@link SeriesStrokeAndPaintApplier} that will be used to format a chart + */ + protected abstract SeriesStrokeAndPaintApplier newStrokeAndPaintApplier(); + + + private JFreeChart createChart(ChartingDefinition chartingDefinition, final Dataset dataset) { + String title = chartingDefinition.getChartTitle(); + String xAxisTitle = chartingDefinition.getXAxisTitle(); + String yAxisTitle = chartingDefinition.getYAxisTitle(); + + final JFreeChart chart = createChartImpl( + title, xAxisTitle, yAxisTitle, + dataset, + PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + addSubtitle(chart, chartingDefinition); - setBackgroundColour(chart); + chart.setBackgroundPaint(BLUE_GRADIENT); + _seriesPainter.applySeriesAppearance(chart, chartingDefinition.getSeriesDefinitions(), newStrokeAndPaintApplier()); + + return chart; } private void addSubtitle(JFreeChart chart, ChartingDefinition chartingDefinition) @@ -46,13 +104,9 @@ public abstract class BaseChartBuilder implements ChartBuilder } } - private void setBackgroundColour(JFreeChart chart) + void setSeriesPainter(SeriesPainter seriesPainter) { - chart.setBackgroundPaint(BLUE_GRADIENT); + _seriesPainter = seriesPainter; } - public abstract JFreeChart createChartImpl(String title, String xAxisTitle, - String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, - boolean showUrls); - } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java index a6c63f4560..0d08fd8ad1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java @@ -20,40 +20,36 @@ package org.apache.qpid.disttest.charting.chartbuilder; -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; +import org.jfree.data.general.Dataset; public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder { - private final SeriesBuilder _seriesBuilder; - public CategoryDataSetBasedChartBuilder(SeriesBuilder seriesBuilder) { - _seriesBuilder = seriesBuilder; + super(seriesBuilder); } @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) + protected DatasetHolder newDatasetHolder() { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() + return new DatasetHolder() { + final private DefaultCategoryDataset _dataset = new DefaultCategoryDataset(); + @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - String x = String.valueOf(row[0]); - double y = Double.parseDouble(row[1].toString()); - dataset.addValue( y, seriesDefinition.getSeriesLegend(), x); + String x = row.dimensionAsString(0); + double y = row.dimensionAsDouble(1); + _dataset.addValue(y, seriesDefinition.getSeriesLegend(), x); } @Override @@ -68,17 +64,33 @@ public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder // unused } - }); + @Override + public int getNumberOfDimensions() + { + return 2; + } - _seriesBuilder.build(chartingDefinition.getSeries()); + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, - dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new CategoryStrokeAndPaintApplier(); + } + @Override + protected final JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = createCategoryChart(title, xAxisTitle, yAxisTitle, dataset, plotOrientation, showLegend, showToolTips, showUrls); chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); - - addCommonChartAttributes(chart, chartingDefinition); - return chart; } + + protected abstract JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java new file mode 100644 index 0000000000..cbf5cbe515 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.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.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; +import java.awt.Stroke; + +import org.jfree.chart.JFreeChart; + +class CategoryStrokeAndPaintApplier implements SeriesStrokeAndPaintApplier +{ + @Override + public void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart) + { + targetChart.getCategoryPlot().getRenderer().setSeriesStroke(seriesIndex, stroke); + } + + @Override + public void setSeriesPaint(int seriesIndex, Color colour, JFreeChart targetChart) + { + targetChart.getCategoryPlot().getRenderer().setSeriesPaint(seriesIndex, colour); + } +}
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java index f4e11a2c4d..63a0573676 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java @@ -39,8 +39,10 @@ public class ChartBuilderFactory return new BarChart3DBuilder(seriesBuilder); case XYLINE: return new XYLineChartBuilder(seriesBuilder); + case TIMELINE: + return new TimeSeriesLineChartBuilder(seriesBuilder); case STATISTICAL_BAR: - return new StatisticalBarCharBuilder(seriesBuilder); + return new StatisticalBarChartBuilder(seriesBuilder); default: throw new IllegalArgumentException("Unknown chart type " + chartType); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java new file mode 100644 index 0000000000..49d777c506 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.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.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; + +public class ColorFactory +{ + /** + * Converts a colour name known to the JDK into a {@link Color} instance. Additionally, + * if the work dark_ is prepended to the colour, a darker shade of the same colour is + * produced. + * + * @param colourName + * @return colour instance + */ + public static Color toColour(String colourName) + { + boolean darkVersion = false; + if (colourName.toLowerCase().startsWith("dark_")) + { + colourName = colourName.replaceFirst("(?i)dark_", ""); + darkVersion = true; + } + + Color colour = getColourFromStaticField(colourName); + if (darkVersion) + { + return colour.darker(); + } + else + { + return colour; + } + } + + private static Color getColourFromStaticField(String colourName) + { + try + { + return (Color) Color.class.getField(colourName.toLowerCase()).get(null); + } + catch (Exception e) + { + throw new RuntimeException("Could not find colour for " + colourName, e); + } + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java index 27fff12da0..b92a25f5ac 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java @@ -34,7 +34,7 @@ public class LineChart3DBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java index 40f3a09b6b..3f5b18acda 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java @@ -35,7 +35,7 @@ public class LineChartBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java new file mode 100644 index 0000000000..854635dc87 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java @@ -0,0 +1,63 @@ +/* + * 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.qpid.disttest.charting.chartbuilder; + +import java.awt.BasicStroke; +import java.util.List; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.chart.JFreeChart; + +public class SeriesPainter +{ + public void applySeriesAppearance(JFreeChart chart, List<SeriesDefinition> seriesDefinitions, SeriesStrokeAndPaintApplier strokeAndPaintApplier) + { + for (int i = 0; i < seriesDefinitions.size(); i++) + { + SeriesDefinition seriesDefinition = seriesDefinitions.get(i); + if (seriesDefinition.getSeriesColourName() != null) + { + strokeAndPaintApplier.setSeriesPaint(i, ColorFactory.toColour(seriesDefinition.getSeriesColourName()), chart); + } + if (seriesDefinition.getStrokeWidth() != null) + { + // Negative width used to signify dashed + boolean dashed = seriesDefinition.getStrokeWidth() < 0; + float width = Math.abs(seriesDefinition.getStrokeWidth()); + BasicStroke stroke = buildStrokeOfWidth(width, dashed); + strokeAndPaintApplier.setSeriesStroke(i, stroke, chart); + } + } + } + + private BasicStroke buildStrokeOfWidth(float width, boolean dashed) + { + final BasicStroke stroke; + if (dashed) + { + stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[] {5.0f, 3.0f}, 0.0f); + } + else + { + stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + } + return stroke; + } +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.java new file mode 100644 index 0000000000..4d6c37a9f4 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.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.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; +import java.awt.Stroke; + +import org.jfree.chart.JFreeChart; + +/** + * Applies the supplied stroke and color to a series in the target chart. + * Multiple implementations exist to because of the various chart types. + */ +public interface SeriesStrokeAndPaintApplier +{ + void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart); + void setSeriesPaint(int seriesIndex, Color color, JFreeChart targetChart); +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java index 86c3f62e09..c5ad2d7dad 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java @@ -22,10 +22,10 @@ package org.apache.qpid.disttest.charting.chartbuilder; import java.awt.Font; -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; @@ -39,33 +39,27 @@ import org.jfree.data.general.Dataset; import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; import org.jfree.data.statistics.StatisticalCategoryDataset; -public class StatisticalBarCharBuilder extends BaseChartBuilder +public class StatisticalBarChartBuilder extends BaseChartBuilder { - private final SeriesBuilder _seriesBuilder; - - public StatisticalBarCharBuilder(SeriesBuilder seriesBuilder) + public StatisticalBarChartBuilder(SeriesBuilder seriesBuilder) { - _seriesBuilder = seriesBuilder; + super(seriesBuilder); } @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) + protected DatasetHolder newDatasetHolder() { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset(); - - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() + return new DatasetHolder() { + private final DefaultStatisticalCategoryDataset _dataset = new DefaultStatisticalCategoryDataset(); + @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - String x = String.valueOf(row[0]); - double mean = Double.parseDouble(row[1].toString()); - double stdDev = Double.parseDouble(row[2].toString()); - dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x); + String x = row.dimensionAsString(0); + double mean = row.dimensionAsDouble(1); + double stdDev = row.dimensionAsDouble(2); + _dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x); } @Override @@ -80,18 +74,24 @@ public class StatisticalBarCharBuilder extends BaseChartBuilder // unused } - }); - - _seriesBuilder.build(chartingDefinition.getSeries()); - - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, dataset, PLOT_ORIENTATION, SHOW_LEGEND, - SHOW_TOOL_TIPS, SHOW_URLS); - - chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); + @Override + public int getNumberOfDimensions() + { + return 3; + } - addCommonChartAttributes(chart, chartingDefinition); + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } - return chart; + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new CategoryStrokeAndPaintApplier(); } @Override @@ -105,6 +105,9 @@ public class StatisticalBarCharBuilder extends BaseChartBuilder CategoryPlot plot = new CategoryPlot((StatisticalCategoryDataset) dataset, xAxis, yAxis, renderer); JFreeChart chart = new JFreeChart(title, new Font("Arial", Font.PLAIN, 10), plot, true); + + chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); + return chart; } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java new file mode 100644 index 0000000000..803a098dfa --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java @@ -0,0 +1,70 @@ +/* + * 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.qpid.disttest.charting.chartbuilder; + +import java.util.Date; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; +import org.jfree.data.general.Dataset; +import org.jfree.data.time.Millisecond; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; + +class TimeSeriesHolder implements DatasetHolder +{ + private final TimeSeriesCollection _timeSeriesCollection = new TimeSeriesCollection(); + private TimeSeries _timeSeries; + + @Override + public void beginSeries(SeriesDefinition seriesDefinition) + { + _timeSeries = new TimeSeries(seriesDefinition.getSeriesLegend()); + } + + @Override + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) + { + Date x = row.dimensionAsDate(0); + double y = row.dimensionAsDouble(1); + RegularTimePeriod jfreeChartDate = new Millisecond(x); + _timeSeries.add(jfreeChartDate, y); + } + + @Override + public void endSeries(SeriesDefinition seriesDefinition) + { + _timeSeriesCollection.addSeries(_timeSeries); + } + + @Override + public int getNumberOfDimensions() + { + return 2; + } + + @Override + public Dataset getPopulatedDataset() + { + return _timeSeriesCollection; + } +}
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java new file mode 100644 index 0000000000..7249ae6332 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java @@ -0,0 +1,59 @@ +/* + * 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.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.general.Dataset; +import org.jfree.data.xy.XYDataset; + +public class TimeSeriesLineChartBuilder extends XYDataSetBasedChartBuilder +{ + public TimeSeriesLineChartBuilder(SeriesBuilder seriesBuilder) + { + super(seriesBuilder); + } + + @Override + protected DatasetHolder newDatasetHolder() + { + return new TimeSeriesHolder(); + } + + @Override + public JFreeChart createChartImpl(String title, String xAxisTitle, + String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, + boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = ChartFactory.createTimeSeriesChart( + title, + xAxisTitle, + yAxisTitle, + (XYDataset)dataset, + showLegend, + showToolTips, + showUrls); + + return chart; + } +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java index 87d61ca2ee..575712f06c 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java @@ -19,38 +19,34 @@ */ package org.apache.qpid.disttest.charting.chartbuilder; +import java.awt.Color; +import java.awt.Stroke; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.data.general.Dataset; import org.jfree.data.xy.DefaultXYDataset; public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder { - private final SeriesBuilder _seriesBuilder; - public XYDataSetBasedChartBuilder(SeriesBuilder seriesBuilder) { - this._seriesBuilder = seriesBuilder; + super(seriesBuilder); } @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) + protected DatasetHolder newDatasetHolder() { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultXYDataset dataset = new DefaultXYDataset(); - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() + return new DatasetHolder() { + private final DefaultXYDataset _dataset = new DefaultXYDataset(); private List<Double[]> _xyPairs = null; @Override @@ -60,20 +56,24 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder } @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, - Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - double x = Double.parseDouble(row[0].toString()); - double y = Double.parseDouble(row[1].toString()); + double x = row.dimensionAsDouble(0); + double y = row.dimensionAsDouble(1); _xyPairs.add(new Double[] {x, y}); } - @Override public void endSeries(SeriesDefinition seriesDefinition) { double[][] seriesData = listToSeriesDataArray(); - dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData); + _dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData); + } + + @Override + public int getNumberOfDimensions() + { + return 2; } private double[][] listToSeriesDataArray() @@ -86,18 +86,34 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder seriesData[0][i] = xyPair[0]; seriesData[1][i] = xyPair[1]; i++; - } + } return seriesData; } - }); - - _seriesBuilder.build(chartingDefinition.getSeries()); - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, - dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } - addCommonChartAttributes(chart, chartingDefinition); + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new SeriesStrokeAndPaintApplier() + { + @Override + public void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart) + { + targetChart.getXYPlot().getRenderer().setSeriesStroke(seriesIndex, stroke); + } - return chart; + @Override + public void setSeriesPaint(int seriesIndex, Color colour, JFreeChart targetChart) + { + targetChart.getXYPlot().getRenderer().setSeriesPaint(seriesIndex, colour); + } + }; } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java index 04b3f7ed3b..bfe47e598e 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java @@ -30,6 +30,7 @@ public class ChartingDefinition private final ChartType _chartType; private final String _chartTitle; private final String _chartSubtitle; + private final String _chartDescription; private final String _xaxisTitle; private final String _yaxisTitle; private final List<SeriesDefinition> _seriesDefinitions; @@ -39,12 +40,14 @@ public class ChartingDefinition final ChartType chartType, final String chartTitle, final String chartSubtitle, + final String chartDescription, final String xaxisTitle, final String yaxisTitle, List<SeriesDefinition> seriesDefinitions) { _chartStemName = chartStemName; _chartType = chartType; _chartTitle = chartTitle; _chartSubtitle = chartSubtitle; + _chartDescription = chartDescription; _xaxisTitle = xaxisTitle; _yaxisTitle = yaxisTitle; _seriesDefinitions = seriesDefinitions; @@ -65,6 +68,10 @@ public class ChartingDefinition return _chartSubtitle; } + public String getChartDescription() + { + return _chartDescription; + } public String getXAxisTitle() { @@ -77,17 +84,14 @@ public class ChartingDefinition return _yaxisTitle; } - - public ChartType getChartType() { return _chartType; } - public List<SeriesDefinition> getSeries() + public List<SeriesDefinition> getSeriesDefinitions() { return Collections.unmodifiableList(_seriesDefinitions); } - } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java index 4cbc9318a9..1988f561b6 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java @@ -39,6 +39,7 @@ public class ChartingDefinitionCreator public static final String CHART_TYPE_KEY = "chartType"; public static final String CHART_TITLE_KEY = "chartTitle"; public static final String CHART_SUBTITLE_KEY = "chartSubtitle"; + public static final String CHART_DESCRIPTION_KEY = "chartDescription"; public static final String XAXIS_TITLE_KEY = "xAxisTitle"; public static final String YAXIS_TITLE_KEY = "yAxisTitle"; @@ -82,6 +83,7 @@ public class ChartingDefinitionCreator final ChartType chartType = ChartType.valueOf(props.getProperty(CHART_TYPE_KEY)); final String chartTitle = props.getProperty(CHART_TITLE_KEY); final String chartSubtitle = props.getProperty(CHART_SUBTITLE_KEY); + final String chartDescription = props.getProperty(CHART_DESCRIPTION_KEY); final String xAxisTitle = props.getProperty(XAXIS_TITLE_KEY); final String yAxisTitle = props.getProperty(YAXIS_TITLE_KEY); @@ -91,8 +93,8 @@ public class ChartingDefinitionCreator chartType, chartTitle, chartSubtitle, - xAxisTitle, - yAxisTitle, seriesDefinitions); + chartDescription, + xAxisTitle, yAxisTitle, seriesDefinitions); return chartDefinition; } catch (IOException e) diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java index a39e906957..d89ff855e2 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java @@ -19,17 +19,24 @@ */ package org.apache.qpid.disttest.charting.definition; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + public class SeriesDefinition { private final String _seriesStatement; private final String _seriesLegend; private final String _seriesDirectory; + private final String _seriesColourName; + private final Integer _seriesStrokeWidth; - public SeriesDefinition(String seriesStatement, String seriesLegend, String seriesDirectory) + public SeriesDefinition(String seriesStatement, String seriesLegend, String seriesDirectory, String seriesColourName, Integer seriesStrokeWidth) { _seriesStatement = seriesStatement; _seriesLegend = seriesLegend; _seriesDirectory = seriesDirectory; + _seriesColourName = seriesColourName; + _seriesStrokeWidth = seriesStrokeWidth; } public String getSeriesStatement() @@ -47,4 +54,22 @@ public class SeriesDefinition return _seriesDirectory; } + public String getSeriesColourName() + { + return _seriesColourName; + } + + public Integer getStrokeWidth() + { + return _seriesStrokeWidth; + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("seriesLegend", _seriesLegend) + .append("seriesStatement", _seriesStatement) + .append("seriesDirectory", _seriesDirectory).toString(); + } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java index fcc11807c8..d47e7488e1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java @@ -30,6 +30,8 @@ public class SeriesDefinitionCreator public static final String SERIES_STATEMENT_KEY_FORMAT = "series.%d.statement"; public static final String SERIES_LEGEND_KEY_FORMAT = "series.%d.legend"; public static final String SERIES_DIRECTORY_KEY_FORMAT = "series.%d.dir"; + public static final String SERIES_COLOUR_NAME_FORMAT = "series.%d.colourName"; + public static final String SERIES_STROKE_WIDTH_FORMAT = "series.%d.strokeWidth"; public List<SeriesDefinition> createFromProperties(Properties properties) { @@ -42,10 +44,13 @@ public class SeriesDefinitionCreator String seriesStatement = properties.getProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, index)); String seriesLegend = properties.getProperty(String.format(SERIES_LEGEND_KEY_FORMAT, index)); String seriesDir = StrSubstitutor.replaceSystemProperties(properties.getProperty(String.format(SERIES_DIRECTORY_KEY_FORMAT, index))); + String seriesColourName = properties.getProperty(String.format(SERIES_COLOUR_NAME_FORMAT, index)); + Integer seriesStrokeWidth = properties.getProperty(String.format(SERIES_STROKE_WIDTH_FORMAT, index)) == null + ? null : Integer.parseInt(properties.getProperty(String.format(SERIES_STROKE_WIDTH_FORMAT, index))); if (seriesStatement != null) { - final SeriesDefinition seriesDefinition = new SeriesDefinition(seriesStatement, seriesLegend, seriesDir); + final SeriesDefinition seriesDefinition = new SeriesDefinition(seriesStatement, seriesLegend, seriesDir, seriesColourName, seriesStrokeWidth); seriesDefinitions.add(seriesDefinition); } else diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java index 7e23953fdb..14fd50facc 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java @@ -20,11 +20,18 @@ package org.apache.qpid.disttest.charting.seriesbuilder; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; -public interface SeriesBuilderCallback +/** + * Accepts data in the form of {@link SeriesDefinition}s and {@link SeriesRow}s, + * and returns it as a {@link Dataset} for use by a JFreeChart chart. + */ +public interface DatasetHolder { - public void beginSeries(SeriesDefinition seriesDefinition); - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row); - public void endSeries(SeriesDefinition seriesDefinition); + int getNumberOfDimensions(); + void beginSeries(SeriesDefinition seriesDefinition); + void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row); + void endSeries(SeriesDefinition seriesDefinition); + Dataset getPopulatedDataset(); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java index a9adce0afc..180aa54c6d 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java @@ -19,7 +19,6 @@ */ package org.apache.qpid.disttest.charting.seriesbuilder; -import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -28,33 +27,52 @@ import java.sql.Statement; import java.util.Iterator; import java.util.List; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; import org.apache.qpid.disttest.charting.ChartingException; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class JdbcCsvSeriesBuilder implements SeriesBuilder +/** + * A {@link SeriesBuilder} that uses JDBC to read series data. + * The actual JDBC URL used is determined by my {@link JdbcUrlGenerator}. + */ +public class JdbcSeriesBuilder implements SeriesBuilder { + private static final Logger LOGGER = LoggerFactory.getLogger(JdbcSeriesBuilder.class); + + private DatasetHolder _datasetHolder; - static + private final JdbcUrlGenerator _jdbcUrlGenerator; + + /** + * @param providedJdbcUrl the JDBC URL. Provide null if the value should be + * inferred by {@link #_jdbcUrlGenerator}. + */ + public JdbcSeriesBuilder(String jdbcDriverClass, String providedJdbcUrl) { - registerCsvDriver(); + registerDriver(jdbcDriverClass); + _jdbcUrlGenerator = new JdbcUrlGenerator(providedJdbcUrl); + LOGGER.info("Created: " + this); } - private SeriesBuilderCallback _callback; - @Override - public void setSeriesBuilderCallback(SeriesBuilderCallback callback) + public void setDatasetHolder(DatasetHolder callback) { - this._callback = callback; + _datasetHolder = callback; } @Override - public void build(List<SeriesDefinition> seriesDefinitions) + public Dataset build(List<SeriesDefinition> seriesDefinitions) { for (Iterator<SeriesDefinition> iterator = seriesDefinitions.iterator(); iterator.hasNext();) { SeriesDefinition series = iterator.next(); buildDataSetForSingleSeries(series); } + return _datasetHolder.getPopulatedDataset(); } private void buildDataSetForSingleSeries(SeriesDefinition seriesDefinition) @@ -63,16 +81,15 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder Statement stmt = null; try { - File seriesDir = getValidatedSeriesDirectory(seriesDefinition); - - conn = DriverManager.getConnection("jdbc:relique:csv:" + seriesDir.getAbsolutePath()); + String jdbcUrl = _jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + conn = DriverManager.getConnection(jdbcUrl); final String seriesStatement = seriesDefinition.getSeriesStatement(); stmt = conn.createStatement(); ResultSet results = stmt.executeQuery(seriesStatement); int columnCount = results.getMetaData().getColumnCount(); - _callback.beginSeries(seriesDefinition); + _datasetHolder.beginSeries(seriesDefinition); while (results.next()) { Object[] row = new Object[columnCount]; @@ -81,9 +98,10 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder row[i] = results.getObject(i+1); } - _callback.addDataPointToSeries(seriesDefinition, row); + SeriesRow seriesRow = SeriesRow.createValidSeriesRow(_datasetHolder.getNumberOfDimensions(), row); + _datasetHolder.addDataPointToSeries(seriesDefinition, seriesRow); } - _callback.endSeries(seriesDefinition); + _datasetHolder.endSeries(seriesDefinition); } catch (SQLException e) { @@ -116,26 +134,24 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder } } - private File getValidatedSeriesDirectory(SeriesDefinition series) - { - File seriesDir = new File(series.getSeriesDirectory()); - if (!seriesDir.isDirectory()) - { - throw new ChartingException("seriesDirectory must be a directory : " + seriesDir); - } - return seriesDir; - } - - private static void registerCsvDriver() throws ExceptionInInitializerError + private void registerDriver(String driverClassName) throws ExceptionInInitializerError { try { - Class.forName("org.relique.jdbc.csv.CsvDriver"); + Class.forName(driverClassName); + LOGGER.info("Loaded JDBC driver class " + driverClassName); } catch (ClassNotFoundException e) { - throw new RuntimeException("Could not load CSV/JDBC driver", e); + throw new RuntimeException("Could not load JDBC driver " + driverClassName, e); } } + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("jdbcUrlGenerator", _jdbcUrlGenerator) + .toString(); + } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java new file mode 100644 index 0000000000..77f367b0f1 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java @@ -0,0 +1,81 @@ +/* + * 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.qpid.disttest.charting.seriesbuilder; + +import static org.apache.commons.lang.StringUtils.isBlank; +import static org.apache.commons.lang.StringUtils.isNotBlank; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; + +public class JdbcUrlGenerator +{ + private String _providedJdbdUrl; + + public static final String DEFAULT_JDBC_DRIVER_NAME = "org.relique.jdbc.csv.CsvDriver"; + + /** + * Used to create the JDBC URL if one has not been passed in. + */ + private static final String CSV_JDBC_URL_BASE = "jdbc:relique:csv:"; + + /** + * @param providedJdbcUrl the JDBC URL. Provide null if the value should be + * inferred. + */ + public JdbcUrlGenerator(String providedJdbcUrl) + { + _providedJdbdUrl = providedJdbcUrl; + } + + /** + * Returns either the provided value ({@link #_providedJdbdUrl}) + * or a CSV JDBC URL pointing at {@link SeriesDefinition#getSeriesDirectory()} value. + */ + public String getJdbcUrl(SeriesDefinition seriesDefinition) + { + String seriesDir = seriesDefinition.getSeriesDirectory(); + + if(_providedJdbdUrl == null) + { + if(isBlank(seriesDir)) + { + throw new IllegalArgumentException("Neither a series directory nor a JDBC url have been specified. Series definition: " + seriesDefinition); + } + return CSV_JDBC_URL_BASE + seriesDir; + } + else + { + if(isNotBlank(seriesDir)) + { + throw new IllegalArgumentException("Both a series directory '" + seriesDir + "' and a JDBC url have been specified. Series definition: " + seriesDefinition); + } + return _providedJdbdUrl; + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("providedJdbdUrl", _providedJdbdUrl) + .toString(); + } +}
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java index 86e471efaf..a865c838c6 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java @@ -22,11 +22,20 @@ package org.apache.qpid.disttest.charting.seriesbuilder; import java.util.List; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; public interface SeriesBuilder { - void build(List<SeriesDefinition> seriesDefinitions); - - void setSeriesBuilderCallback(SeriesBuilderCallback seriesBuilderCallback); + /** + * Uses the supplied {@link SeriesDefinition}s to read the series data + * and pass it to the dataset holder set up in {@link #setDatasetHolder(DatasetHolder)}. + * + * @return the populated dataset + */ + Dataset build(List<SeriesDefinition> seriesDefinitions); + /** + * Stores the supplied dataset holder so it can be populated in {@link #build(List)}. + */ + void setDatasetHolder(DatasetHolder datasetHolder); }
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java new file mode 100644 index 0000000000..9c16866939 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.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.qpid.disttest.charting.seriesbuilder; + +import java.util.Arrays; +import java.util.Date; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * A data point in a chart. Thinly wraps an array to provide a convenient place to validate the number of dimensions, + * and to access dimensions in a typesafe manner. + */ +public class SeriesRow +{ + private final Object[] _dimensions; + + public static SeriesRow createValidSeriesRow(int expectedNumberOfDimensions, Object[] dimensions) + { + int actualNumberOfDimensions = dimensions.length; + if(expectedNumberOfDimensions != actualNumberOfDimensions) + { + throw new IllegalArgumentException("Expected " + expectedNumberOfDimensions + + " dimensions but found " + actualNumberOfDimensions + + " in: " + Arrays.asList(dimensions)); + } + return new SeriesRow(dimensions); + } + + public SeriesRow(Object... dimensions) + { + _dimensions = dimensions; + } + + public Object dimension(int dimension) + { + return _dimensions[dimension]; + } + + public String dimensionAsString(int dimension) + { + return String.valueOf(dimension(dimension)); + } + + public double dimensionAsDouble(int dimension) + { + return Double.parseDouble(dimensionAsString(dimension)); + } + + public Date dimensionAsDate(int dimension) + { + return (Date) dimension(dimension); + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(_dimensions).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + SeriesRow rhs = (SeriesRow) obj; + return new EqualsBuilder().append(_dimensions, rhs._dimensions).isEquals(); + } + + +}
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java index 5d4a9b6b7e..341f01ccd1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java @@ -26,10 +26,11 @@ import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.SortedMap; +import java.util.TreeMap; import org.apache.qpid.disttest.charting.ChartingException; +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.slf4j.Logger; @@ -42,19 +43,19 @@ public class ChartWriter static final String SUMMARY_FILE_NAME = "chart-summary.html"; private File _chartDirectory = new File("."); - private SortedSet<File> _chartFiles = new TreeSet<File>(); + private SortedMap<File,ChartingDefinition> _chartFilesToChartDef = new TreeMap<File, ChartingDefinition>(); - public void writeChartToFileSystem(JFreeChart chart, String chartStemName) + public void writeChartToFileSystem(JFreeChart chart, ChartingDefinition chartDef) { OutputStream pngOutputStream = null; try { - File pngFile = new File(_chartDirectory, chartStemName + ".png"); + File pngFile = new File(_chartDirectory, chartDef.getChartStemName() + ".png"); pngOutputStream = new BufferedOutputStream(new FileOutputStream(pngFile)); ChartUtilities.writeChartAsPNG(pngOutputStream, chart, 600, 400, true, 0); pngOutputStream.close(); - _chartFiles.add(pngFile); + _chartFilesToChartDef.put(pngFile, chartDef); LOGGER.info("Written {} chart", pngFile); } @@ -78,20 +79,21 @@ public class ChartWriter } } - public void writeHtmlSummaryToFileSystem() + public void writeHtmlSummaryToFileSystem(String summaryPageTitle) { - if(_chartFiles.size() < 2) + if(_chartFilesToChartDef.size() < 2) { - LOGGER.info("Only " + _chartFiles.size() + " chart image(s) have been written so no HTML summary file will be produced"); + LOGGER.info("Only {} chart image(s) have been written so no HTML summary file will be produced", _chartFilesToChartDef.size()); return; } - String htmlHeader = + String htmlHeader = String.format( "<html>\n" + " <head>\n" + - " <title>Performance Charts</title>\n" + + " <title>%s</title>\n" + + " <style type='text/css'>figure { float: left; display: table; width: 87px;}</style>\n" + " </head>\n" + - " <body>\n"; + " <body>\n", summaryPageTitle); String htmlFooter = " </body>\n" + @@ -101,22 +103,29 @@ public class ChartWriter try { File summaryFile = new File(_chartDirectory, SUMMARY_FILE_NAME); - LOGGER.debug("About to produce HTML summary file " + summaryFile.getAbsolutePath() + " from charts " + _chartFiles); + LOGGER.debug("About to produce HTML summary file " + summaryFile.getAbsolutePath() + " from charts " + _chartFilesToChartDef); writer = new BufferedWriter(new FileWriter(summaryFile)); writer.write(htmlHeader); writer.write(" <ul>\n"); - for (File chartFile : _chartFiles) + for (File chartFile : _chartFilesToChartDef.keySet()) { writer.write(" <li><a href='#"+ chartFile.getName() +"'>" + chartFile.getName() + "</a></li>\n"); } writer.write(" </ul>\n"); - for (File chartFile : _chartFiles) + for (File chartFile : _chartFilesToChartDef.keySet()) { - writer.write(" <a name='" + chartFile.getName() + "'/>\n"); - writer.write(" <img src='" + chartFile.getName() + "'/>\n"); + ChartingDefinition def = _chartFilesToChartDef.get(chartFile); + writer.write(" <figure>\n"); + writer.write(" <a name='" + chartFile.getName() + "'/>\n"); + writer.write(" <img src='" + chartFile.getName() + "'/>\n"); + if (def.getChartDescription() != null) + { + writer.write(" <figcaption>" + def.getChartDescription() + "</figcaption>\n"); + } + writer.write(" </figure>\n"); } writer.write(htmlFooter); writer.close(); @@ -144,5 +153,6 @@ public class ChartWriter public void setOutputDirectory(final File chartDirectory) { _chartDirectory = chartDirectory; + LOGGER.info("Set chart directory: {}", chartDirectory); } } |