001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.server.charts.deprecated;
021
022import org.jfree.chart.JFreeChart;
023import org.jfree.chart.axis.CategoryAxis;
024import org.jfree.chart.axis.NumberAxis;
025import org.jfree.chart.axis.NumberTickUnit;
026import org.jfree.chart.plot.CategoryPlot;
027import org.jfree.chart.plot.PlotOrientation;
028import org.jfree.chart.renderer.category.BarRenderer;
029import org.jfree.chart.renderer.category.StackedBarRenderer;
030import org.jfree.chart.title.TextTitle;
031import org.jfree.data.category.DefaultCategoryDataset;
032import org.jfree.ui.RectangleInsets;
033
034import java.awt.image.BufferedImage;
035import java.io.IOException;
036import java.util.Map;
037import java.util.StringTokenizer;
038
039public class BarChart extends BaseChartWeb implements DeprecatedChart {
040
041  private BarRenderer renderer = null;
042  protected DefaultCategoryDataset dataset = null;
043  protected CategoryAxis categoryAxis = null;
044  protected NumberAxis numberAxis = null;
045
046  public BarChart(Map<String, String> params) {
047    super(params);
048    jfreechart = new JFreeChart(null, TextTitle.DEFAULT_FONT, new CategoryPlot(), false);
049  }
050
051  @Override
052  protected BufferedImage getChartImage() throws IOException {
053    configure();
054    return getBufferedImage(jfreechart);
055  }
056
057  protected void configure() {
058    configureChart(jfreechart, false);
059    configureCategoryDataset();
060    configureCategoryAxis();
061    configureRenderer();
062    configureRangeAxis();
063    configureCategoryPlot();
064    applyParams();
065  }
066
067  protected void configureCategoryPlot() {
068    CategoryPlot plot = jfreechart.getCategoryPlot();
069    plot.setNoDataMessage(DEFAULT_MESSAGE_NODATA);
070    plot.setInsets(RectangleInsets.ZERO_INSETS); // To remove inner space around chart
071    plot.setDataset(dataset);
072    plot.setDomainAxis(categoryAxis);
073    plot.setRenderer(renderer);
074    plot.setRangeAxis(numberAxis);
075  }
076
077  protected void configureCategoryDataset() {
078    dataset = new DefaultCategoryDataset();
079  }
080
081  protected void configureCategoryAxis() {
082    categoryAxis = new CategoryAxis();
083    categoryAxis.setLabelFont(DEFAULT_FONT);
084    categoryAxis.setLabelPaint(BASE_COLOR);
085    categoryAxis.setTickLabelFont(DEFAULT_FONT);
086    categoryAxis.setTickLabelPaint(BASE_COLOR);
087    categoryAxis.setVisible(false);
088  }
089
090  protected void configureRenderer() {
091    if (params.get(BaseChartWeb.CHART_PARAM_TYPE).equals(BaseChartWeb.STACKED_BAR_CHART)) {
092      renderer = new StackedBarRenderer();
093    } else {
094      renderer = new BarRenderer();
095    }
096    renderer.setItemMargin(0.0);
097    renderer.setDrawBarOutline(false);
098  }
099
100  protected void configureRangeAxis() {
101    numberAxis = new NumberAxis();
102    numberAxis.setLabelFont(DEFAULT_FONT);
103    numberAxis.setLabelPaint(BASE_COLOR);
104    numberAxis.setTickLabelFont(DEFAULT_FONT);
105    numberAxis.setTickLabelPaint(BASE_COLOR);
106    numberAxis.setTickMarksVisible(true);
107    numberAxis.setVisible(false);
108    numberAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
109  }
110
111  protected void applyCommomParamsBar() {
112    // -- Plot
113    CategoryPlot plot = jfreechart.getCategoryPlot();
114    plot.setOrientation(BaseChartWeb.BAR_CHART_VERTICAL.equals(params.get(BaseChartWeb.CHART_PARAM_TYPE))
115      || BaseChartWeb.BAR_CHART_VERTICAL_CUSTOM.equals(params.get(BaseChartWeb.CHART_PARAM_TYPE)) ?
116        PlotOrientation.VERTICAL :
117        PlotOrientation.HORIZONTAL);
118    plot.setOutlineVisible("y".equals(params.get(BaseChartWeb.CHART_PARAM_OUTLINE_VISIBLE)));
119    plot.setRangeGridlinesVisible("y".equals(params.get(BaseChartWeb.CHART_PARAM_OUTLINE_RANGEGRIDLINES_VISIBLE)));
120    String insetsParam = params.get(CHART_PARAM_INSETS);
121    if (isParamValueValid(insetsParam)) {
122      double insets = convertParamToDouble(insetsParam);
123      RectangleInsets rectangleInsets = new RectangleInsets(insets, insets, insets, insets);
124      plot.setInsets(rectangleInsets);
125    }
126
127    // -- Category Axis
128    boolean categoryAxisIsVisible = "y".equals(params.get(BaseChartWeb.CHART_PARAM_CATEGORIES_AXISMARGIN_VISIBLE));
129    double categoryAxisUpperMargin = convertParamToDouble(params.get(BaseChartWeb.CHART_PARAM_CATEGORIES_AXISMARGIN_UPPER), DEFAULT_CATEGORIES_AXISMARGIN);
130    double categoryAxisLowerMargin = convertParamToDouble(params.get(BaseChartWeb.CHART_PARAM_CATEGORIES_AXISMARGIN_LOWER), DEFAULT_CATEGORIES_AXISMARGIN);
131    categoryAxis.setVisible(categoryAxisIsVisible);
132    categoryAxis.setTickLabelsVisible(categoryAxisIsVisible);
133    categoryAxis.setLowerMargin(categoryAxisLowerMargin);
134    categoryAxis.setUpperMargin(categoryAxisUpperMargin);
135
136    // -- Range Axis
137    boolean rangeAxisIsVisible = "y".equals(params.get(BaseChartWeb.CHART_PARAM_RANGEAXIS_VISIBLE));
138    double rangeAxisUpperMargin = convertParamToDouble(params.get(BaseChartWeb.CHART_PARAM_SERIES_AXISMARGIN_UPPER), DEFAULT_SERIES_AXISMARGIN);
139    double rangeAxisLowerMargin = convertParamToDouble(params.get(BaseChartWeb.CHART_PARAM_SERIES_AXISMARGIN_LOWER), DEFAULT_SERIES_AXISMARGIN);
140    numberAxis.setTickLabelsVisible(rangeAxisIsVisible);
141    numberAxis.setVisible(rangeAxisIsVisible);
142    numberAxis.setLowerMargin(rangeAxisLowerMargin);
143    numberAxis.setUpperMargin(rangeAxisUpperMargin);
144    String rangeMax = params.get(BaseChartWeb.CHART_PARAM_RANGEMAX);
145    if (isParamValueValid(rangeMax)) {
146      double iRangeMax = Double.parseDouble(rangeMax);
147      numberAxis.setRange(0.0, iRangeMax);
148    }
149    String tickUnit = params.get(BaseChartWeb.CHART_PARAM_SERIES_AXISMARGIN_TICKUNIT);
150    if (isParamValueValid(tickUnit)) {
151      numberAxis.setTickUnit(new NumberTickUnit(convertParamToDouble(tickUnit)));
152    }
153  }
154
155  private void applyParams() {
156    applyCommonParams();
157    applyCommomParamsBar();
158
159    configureColors(params.get(BaseChartWeb.CHART_PARAM_COLORS), renderer);
160    addMeasures(params.get(BaseChartWeb.CHART_PARAM_VALUES));
161  }
162
163  private void addMeasures(String values) {
164    if (values != null && values.length() > 0) {
165      // Values
166      StringTokenizer stValues = new StringTokenizer(values, ",");
167      int nbValues = stValues.countTokens();
168
169      // Categories
170      String categoriesParam = params.get(BaseChartWeb.CHART_PARAM_CATEGORIES);
171      String[] categoriesSplit;
172      if (categoriesParam != null && categoriesParam.length() > 0) {
173        categoriesSplit = categoriesParam.split(",");
174      } else {
175        categoriesSplit = new String[1];
176        categoriesSplit[0] = BaseChartWeb.DEFAULT_NAME_CATEGORY;
177      }
178
179      // Series
180      String seriesParam = params.get(BaseChartWeb.CHART_PARAM_SERIES);
181      String[] seriesSplit = null;
182      if (seriesParam != null && seriesParam.length() > 0) {
183        seriesSplit = seriesParam.split(",");
184      } else {
185        seriesSplit = new String[nbValues];
186        for (int i = 0; i < nbValues; i++) {
187          seriesSplit[i] = BaseChartWeb.DEFAULT_NAME_SERIE + i;
188        }
189      }
190
191      for (String currentCategory : categoriesSplit) {
192        for (String currentSerie : seriesSplit) {
193          double currentValue = 0.0;
194          if (stValues.hasMoreTokens()) {
195            try {
196              currentValue = Double.parseDouble(stValues.nextToken());
197            } catch (NumberFormatException e) {
198              // ignore
199            }
200          }
201          dataset.addValue(currentValue, currentSerie, currentCategory);
202        }
203      }
204    }
205  }
206
207}