/* * Copyright (C) 2008 Digital Sundhed (SDSD) * * All source code and information supplied as part of chronos * is copyright to its contributers. * * The source code has been released under a dual license - meaning you can * use either licensed version of the library with your code. * * It is released under the Common Public License 1.0, a copy of which can * be found at the link below. * http://www.opensource.org/licenses/cpl.php * * It is released under the LGPL (GNU Lesser General Public License), either * version 2.1 of the License, or (at your option) any later version. A copy * of which can be found at the link below. * http://www.gnu.org/copyleft/lesser.html */ package org.codehaus.mojo.chronos.report; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ResourceBundle; import org.codehaus.doxia.sink.Sink; import org.codehaus.mojo.chronos.ReportConfig; import org.codehaus.mojo.chronos.chart.ChartSource; import org.codehaus.mojo.chronos.chart.GraphGenerator; import org.codehaus.mojo.chronos.responsetime.GroupedResponsetimeSamples; import org.codehaus.mojo.chronos.responsetime.ResponsetimeSampleGroup; import org.codehaus.mojo.chronos.responsetime.ResponsetimeSamples; /** * Generates the JMeter report. * * @author ksr@lakeside.dk */ public final class ReportGenerator { private static final String IMG_EXT = ".png"; private NumberFormat formatter; private ReportConfig config; private ResourceBundle bundle; private ReportSink reportSink; private Sink sink; private GraphGenerator graphs; /** * @param bundle * The {@link ResourceBundle} to extract messages from * @param config * The {@link ReportConfig} of the report generation */ public ReportGenerator(ResourceBundle bundle, ReportConfig config, GraphGenerator graphs) { this.formatter = new DecimalFormat("#.#"); this.bundle = bundle; this.config = config; this.graphs = graphs; } /** * Generate a report (as an html page). * * @param aSink * The {@link Sink} to output the report content to * @param samples * The {@link ResponsetimeSamples} to create a report from */ public void doGenerateReport(Sink aSink, ResponsetimeSamples samples) { this.reportSink = new ReportSink(bundle, aSink); this.sink = aSink; aSink.head(); aSink.text(bundle.getString("chronos.description")); aSink.head_(); aSink.body(); constructReportHeaderSection(); if(config.isShowsummary()) { constructReportSummarySection(samples); } if(config.isShowdetails() && samples instanceof GroupedResponsetimeSamples) { constructIndividualTestsSection((GroupedResponsetimeSamples)samples); } aSink.body_(); aSink.flush(); aSink.close(); } private void constructReportHeaderSection() { String title = config.getTitle(); String description = config.getDescription(); String anchor = "Report" + config.getId(); reportSink.constructHeaderSection(title, description, anchor); } private void constructReportSummarySection(ResponsetimeSamples samples) { String text = bundle.getString("chronos.label.summary"); String anchor = "Summary" + config.getId(); reportSink.title2(text, anchor); constructReportHotLinks(); if(config.isShowinfotable() && samples instanceof GroupedResponsetimeSamples) { sink.table(); sink.tableRow(); reportSink.th("chronos.label.tests"); if(config.isShowtimeinfo()) { reportSink.th("chronos.label.percentile95"); reportSink.th("chronos.label.averagetime"); } reportSink.th("chronos.label.iterations"); reportSink.th("chronos.label.successrate"); sink.tableRow_(); GroupedResponsetimeSamples groupedSamples = (GroupedResponsetimeSamples)samples; for (Iterator it = groupedSamples.getSampleGroups().iterator(); it.hasNext();) { ResponsetimeSampleGroup sampleGroup = (ResponsetimeSampleGroup)it.next(); sink.tableRow(); reportSink.sinkCellLink(sampleGroup.getName(), "#a" + sampleGroup.getIndex() + config.getId()); if(config.isShowtimeinfo()) { int responsetimedivider = config.getResponsetimedivider(); double percentile95 = sampleGroup.getPercentile95(responsetimedivider); reportSink.sinkCell(formatter.format(percentile95)); double average = sampleGroup.getAverage(config.getResponsetimedivider()); reportSink.sinkCell(formatter.format(average)); } // Line merged from Atlessian. // reportSink.sinkCell("" + sampleGroup.size() * config.getResponsetimedivider()); reportSink.sinkCell("" + sampleGroup.size()); reportSink.sinkCell(formatter.format(sampleGroup.getSuccessrate()) + " %"); sink.tableRow_(); } sink.table_(); reportSink.sinkLineBreak(); } if(!config.isShowsummarycharts()) { return; } for (Iterator iterator = graphs.getSummaryChartSources().iterator(); iterator.hasNext();) { ChartSource chartSource = (ChartSource)iterator.next(); if(chartSource.isEnabled(bundle, config)) { reportSink.graphics(chartSource.getFileName(bundle, config) + IMG_EXT); } } } private void constructIndividualTestsSection(GroupedResponsetimeSamples samples) { reportSink.title2(bundle.getString("chronos.label.testcases"), "Test_Cases" + config.getId()); constructReportHotLinks(); for (Iterator it = samples.getSampleGroups().iterator(); it.hasNext();) { ResponsetimeSampleGroup sampleGroup = (ResponsetimeSampleGroup)it.next(); reportSink.title3(sampleGroup.getName(), sampleGroup.getIndex() + config.getId()); if(config.isShowinfotable()) { sink.table(); List headerLabels = new ArrayList(); if(config.isShowtimeinfo()) { headerLabels.add("chronos.label.mintime"); headerLabels.add("chronos.label.averagetime"); headerLabels.add("chronos.label.percentile95"); headerLabels.add("chronos.label.maxtime"); } headerLabels.add("chronos.label.iterations"); headerLabels.add("chronos.label.failures"); headerLabels.add("chronos.label.successrate"); List dataLine = new ArrayList(); if(config.isShowtimeinfo()) { dataLine.add(formatter.format(sampleGroup.getMin(config.getResponsetimedivider()))); dataLine.add(formatter.format(sampleGroup.getAverage(config.getResponsetimedivider()))); dataLine.add(formatter.format(sampleGroup.getPercentile95(config.getResponsetimedivider()))); dataLine.add(formatter.format(sampleGroup.getMax(config.getResponsetimedivider()))); } dataLine.add("" + sampleGroup.size() * config.getResponsetimedivider()); dataLine.add(formatter.format(sampleGroup.getFailed())); dataLine.add(formatter.format(sampleGroup.getSuccessrate()) + " %"); List dataLines = new ArrayList(); dataLines.add(dataLine); reportSink.table(headerLabels, dataLines); } for (Iterator iterator = graphs.getDetailsChartSources(sampleGroup.getName()).iterator(); iterator .hasNext();) { ChartSource source = (ChartSource)iterator.next(); if(source.isEnabled(bundle, config)) { reportSink.graphics(source.getFileName(bundle, config) + IMG_EXT); } } } reportSink.sinkLineBreak(); } private void constructReportHotLinks() { sink.section3(); if(config.isShowsummary()) { reportSink.sinkLink(bundle.getString("chronos.label.summary"), "Summary" + config.getId()); } if(config.isShowdetails()) { reportSink.sinkLink(bundle.getString("chronos.label.testcases"), "Test_Cases" + config.getId()); } sink.section3_(); } }