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 */
020 package org.sonar.server.charts.deprecated;
021
022 import org.jfree.chart.JFreeChart;
023 import org.jfree.chart.axis.CategoryAxis;
024 import org.jfree.chart.axis.NumberAxis;
025 import org.jfree.chart.axis.NumberTickUnit;
026 import org.jfree.chart.plot.CategoryPlot;
027 import org.jfree.chart.plot.PlotOrientation;
028 import org.jfree.chart.renderer.category.BarRenderer;
029 import org.jfree.chart.renderer.category.StackedBarRenderer;
030 import org.jfree.chart.title.TextTitle;
031 import org.jfree.data.category.DefaultCategoryDataset;
032 import org.jfree.ui.RectangleInsets;
033
034 import java.awt.image.BufferedImage;
035 import java.io.IOException;
036 import java.util.Map;
037 import java.util.StringTokenizer;
038
039 public 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 boolean categoriesPresent = categoriesParam != null && categoriesParam.length() > 0;
172 String[] categoriesSplit;
173 if (categoriesPresent) {
174 categoriesSplit = categoriesParam.split(",");
175 } else {
176 categoriesSplit = new String[1];
177 categoriesSplit[0] = BaseChartWeb.DEFAULT_NAME_CATEGORY;
178 }
179
180 // Series
181 String seriesParam = params.get(BaseChartWeb.CHART_PARAM_SERIES);
182 boolean seriesPresent = seriesParam != null && seriesParam.length() > 0;
183 String[] seriesSplit = null;
184 if (seriesPresent) {
185 seriesSplit = seriesParam.split(",");
186 } else {
187 seriesSplit = new String[nbValues];
188 for (int i = 0; i < nbValues; i++) {
189 seriesSplit[i] = BaseChartWeb.DEFAULT_NAME_SERIE + i;
190 }
191 }
192
193 for (String currentCategory : categoriesSplit) {
194 for (String currentSerie : seriesSplit) {
195 double currentValue = 0.0;
196 if (stValues.hasMoreTokens()) {
197 try {
198 currentValue = Double.parseDouble(stValues.nextToken());
199 } catch (NumberFormatException e) {
200 // ignore
201 }
202 }
203 dataset.addValue(currentValue, currentSerie, currentCategory);
204 }
205 }
206 }
207 }
208
209 }