001: /********************************************************************************
002: * CruiseControl, a Continuous Integration Toolkit
003: * Copyright (c) 2001, ThoughtWorks, Inc.
004: * 200 E. Randolph, 25th Floor
005: * Chicago, IL 60601 USA
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * + Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * + Redistributions in binary form must reproduce the above
016: * copyright notice, this list of conditions and the following
017: * disclaimer in the documentation and/or other materials provided
018: * with the distribution.
019: *
020: * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021: * names of its contributors may be used to endorse or promote
022: * products derived from this software without specific prior
023: * written permission.
024: *
025: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036: ********************************************************************************/package net.sourceforge.cruisecontrol.chart;
037:
038: import java.text.NumberFormat;
039: import java.text.SimpleDateFormat;
040: import java.util.Calendar;
041: import java.util.Date;
042: import java.util.Iterator;
043: import java.util.Map;
044:
045: import net.sourceforge.cruisecontrol.BuildInfo;
046: import net.sourceforge.cruisecontrol.BuildInfoSummary;
047: import net.sourceforge.cruisecontrol.util.TimeNumberFormat;
048:
049: import org.jfree.chart.JFreeChart;
050: import org.jfree.chart.axis.DateAxis;
051: import org.jfree.chart.axis.NumberAxis;
052: import org.jfree.chart.axis.NumberTickUnit;
053: import org.jfree.chart.plot.XYPlot;
054: import org.jfree.chart.renderer.StandardXYItemRenderer;
055: import org.jfree.data.time.Minute;
056: import org.jfree.data.time.TimeSeries;
057: import org.jfree.data.time.TimeSeriesCollection;
058:
059: import de.laures.cewolf.ChartPostProcessor;
060: import de.laures.cewolf.DatasetProduceException;
061:
062: public class TimeChartData extends AbstractCruiseControlChartData
063: implements ChartPostProcessor {
064:
065: private static final long serialVersionUID = -5159867264828131088L;
066:
067: public Object produceDataset(Map params)
068: throws DatasetProduceException {
069: BuildInfoSummary summary = (BuildInfoSummary) params
070: .get("buildInfo");
071: TimeSeries brokenSeries = new TimeSeries("Broken Builds",
072: Minute.class);
073: TimeSeries goodSeries = new TimeSeries("Good Builds",
074: Minute.class);
075: for (Iterator iter = summary.iterator(); iter.hasNext();) {
076: BuildInfo buildInfo = (BuildInfo) iter.next();
077: Date buildTime = buildInfo.getBuildDate();
078: double timeValue = extractTimeOfDay(buildTime);
079: Minute timePeriod = new Minute(buildTime);
080: TimeSeries seriesToAddTo = buildInfo.isSuccessful() ? goodSeries
081: : brokenSeries;
082: if (seriesToAddTo.getDataPair(timePeriod) == null) {
083: seriesToAddTo.add(timePeriod, timeValue);
084: } else {
085: System.err
086: .println("multiple logs in the same minute; ignoring: "
087: + buildInfo.getLogName());
088: }
089: }
090: TimeSeriesCollection dataset = new TimeSeriesCollection();
091: dataset.addSeries(brokenSeries);
092: dataset.addSeries(goodSeries);
093: return dataset;
094: }
095:
096: /**
097: * @param buildTime
098: * @return Only the time part of the Date
099: */
100: private double extractTimeOfDay(Date buildTime) {
101: Calendar buildCalendar = Calendar.getInstance();
102: buildCalendar.setTime(buildTime);
103: double timeValue = buildCalendar.get(Calendar.HOUR_OF_DAY);
104: timeValue = timeValue * 60 + buildCalendar.get(Calendar.MINUTE);
105: timeValue = timeValue * 60 + buildCalendar.get(Calendar.SECOND);
106: timeValue = timeValue * 1000
107: + buildCalendar.get(Calendar.MILLISECOND);
108: return timeValue;
109: }
110:
111: public String getProducerId() {
112: return "TimeChartData DatasetProducer";
113: }
114:
115: /**
116: * @see ChartPostProcessor#processChart(Object, Map)
117: */
118: public void processChart(Object chartObject, Map params) {
119: JFreeChart chart = (JFreeChart) chartObject;
120: XYPlot plot = chart.getXYPlot();
121: configurePlotRendererForShapesOnly(plot);
122: setXAxisFormat(plot);
123: setYAxisFormat(plot);
124: }
125:
126: /**
127: * @param plot
128: */
129: private void setYAxisFormat(XYPlot plot) {
130: NumberAxis yAxis = (NumberAxis) plot.getVerticalAxis();
131: NumberFormat yAxisFormat = new TimeNumberFormat();
132: yAxis.setNumberFormatOverride(yAxisFormat);
133: yAxis.setMinimumAxisValue(0);
134: yAxis.setMaximumAxisValue(24 * 60 * 60 * 1000);
135: yAxis.setTickUnit(new NumberTickUnit(2 * 60 * 60 * 1000));
136: }
137:
138: /**
139: * @param plot
140: */
141: private void setXAxisFormat(XYPlot plot) {
142: DateAxis xAxis = (DateAxis) plot.getHorizontalValueAxis();
143: xAxis.setDateFormatOverride(new SimpleDateFormat("dd/MM"));
144: }
145:
146: /**
147: * @param plot
148: */
149: private void configurePlotRendererForShapesOnly(XYPlot plot) {
150: StandardXYItemRenderer renderer = new StandardXYItemRenderer(
151: StandardXYItemRenderer.SHAPES);
152: renderer.setDefaultShapeFilled(true);
153: plot.setRenderer(renderer);
154: }
155: }
|