package com.c2c.controller; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.block.BlockBorder; import org.jfree.chart.block.RectangleConstraint; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PiePlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.chart.renderer.category.StandardBarPainter; import org.jfree.chart.title.LegendTitle; import org.jfree.data.Range; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.general.DefaultPieDataset; import org.jfree.ui.Size2D; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** * @author pmauduit, stolen from tbonfort's code from cdc_geodecisionnel project */ @Controller @RequestMapping("/getoverlayicon") public class GetOverlayIcon extends AbstractQueryingController { public static final Color TRANSPARENT = new Color(0, 0, 0, 0); public enum ChartType { PIE, BAR; } private static Boolean legend ; @RequestMapping(method = RequestMethod.GET) public void getchart(HttpServletRequest request, HttpServletResponse response, @RequestParam("DATA") String data, @RequestParam("TYPE") String type, @RequestParam("WIDTH") int width, @RequestParam("HEIGHT") int height, @RequestParam(value = "LABELS", required = false) String labels, @RequestParam(value = "FORMAT", required = false) String format, @RequestParam(value = "LEGEND", required = false) Boolean onlyLegend ) throws Exception { final OutputStream outputStream = response.getOutputStream(); if (format == null) { response.setContentType("image/png"); } else { response.setContentType(format); } if (onlyLegend == null) { this.legend = false; } else { this.legend = onlyLegend; response.setContentType(format); response.addHeader("Cache-Control", "no-cache"); response.addHeader("Expires", "-1"); } if (labels == null) labels = ""; try { switch (ChartType.valueOf(type.toUpperCase())) { case PIE: renderPieChart(parseData(data), parseLabels(labels), width, height, outputStream); break; case BAR: renderBarChart(parseData(data), parseLabels(labels), width, height, outputStream); break; default: throw new IllegalArgumentException(type + " not supported overlay type"); } } catch (Exception e) { e.printStackTrace(); } finally { outputStream.close(); } } private static void renderPieChart(double[] data, String[] labels, int width, int height, OutputStream outputStream) throws IOException { DefaultPieDataset pieDataset = new DefaultPieDataset(); for (int i = 0; i < data.length; i++) { if ((labels.length > i) && (! labels[i].equals(""))) pieDataset.setValue(labels[i], data[i]); else /* no label */ pieDataset.setValue(Integer.valueOf(i), data[i]); } JFreeChart chart ; if (legend == false) chart = ChartFactory.createPieChart(null, pieDataset, false, false, false); else chart = ChartFactory.createPieChart(null, pieDataset, true, true, false); chart.setBackgroundPaint(TRANSPARENT); chart.setBorderVisible(false); PiePlot plot = (PiePlot) chart.getPlot(); java.util.List l = pieDataset.getKeys(); for (int i = 0; i < Math.min(pieDataset.getItemCount(), 8); i++) { plot.setSectionPaint((Comparable) l.get(i), GetChart.DEFAULT_COLORS[i]); } plot.setBackgroundPaint(TRANSPARENT); plot.setLabelGenerator(null); plot.setInteriorGap(0); plot.setShadowXOffset(0); plot.setShadowYOffset(0); plot.setOutlineVisible(false); if (legend == false) { ChartUtilities.writeChartAsPNG(outputStream, chart, width, height); } else { LegendTitle lgd = chart.getLegend(); lgd.setMargin(0,0,1,1); lgd.setBackgroundPaint(TRANSPARENT); lgd.setBorder(BlockBorder.NONE); BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); // TODO : should be ok for the main requests, but could overlap in // some cases Size2D size = lgd.arrange(g2, new RectangleConstraint(new Range(0.0, width * 1.5),new Range(0.0, height))); //Size2D size = lgd.arrange(g2, RectangleConstraint.NONE); g2.dispose(); int w = (int) Math.rint(size.width); int h = (int) Math.rint(size.height); BufferedImage img2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g22 = img2.createGraphics(); lgd.draw(g22, new Rectangle2D.Double(0, 0, w, h)); try { ChartUtilities.writeBufferedImageAsPNG(outputStream, img2); }catch (Exception e) { e.printStackTrace(); } finally { g22.dispose(); } } } private static void renderBarChart(double[] data, String[] labels, int width, int height, OutputStream outputStream) throws IOException { DefaultCategoryDataset catDataset = new DefaultCategoryDataset(); for (int i = 0; i < data.length; i++) { //catDataset.setValue(data[i], Integer.valueOf(i), ""); if ((labels.length > i) && (! labels[i].equals(""))) catDataset.setValue(data[i],labels[i], ""); else /* no label */ catDataset.setValue(data[i], Integer.valueOf(i), ""); } JFreeChart chart ; if (legend == false) chart = ChartFactory.createBarChart(null, null, null, catDataset, PlotOrientation.VERTICAL, false, false, false); else chart = ChartFactory.createBarChart(null, null, null, catDataset, PlotOrientation.VERTICAL, true, false, false); chart.setBackgroundPaint(TRANSPARENT); chart.setBorderVisible(false); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setBackgroundPaint(TRANSPARENT); plot.setRangeGridlinesVisible(false); plot.setOutlineVisible(false); plot.getRangeAxis().setAxisLineVisible(false); plot.getRangeAxis().setTickLabelsVisible(false); plot.getRangeAxis().setTickMarksVisible(false); plot.getDomainAxis().setAxisLineVisible(false); plot.getDomainAxis().setTickLabelsVisible(false); plot.getDomainAxis().setTickMarksVisible(false); BarRenderer r = (BarRenderer) plot.getRenderer(); // using predefined colors for (int i = 0; i < Math.min(catDataset.getColumnCount(), 8); i++) { r.setSeriesPaint(i, GetChart.DEFAULT_COLORS[i]); } r.setBarPainter(new StandardBarPainter()); r.setDefaultShadowsVisible(false); r.setDrawBarOutline(false); r.setShadowVisible(false); if (legend == false) { ChartUtilities.writeChartAsPNG(outputStream, chart, width, height); } else { LegendTitle lgd = chart.getLegend(); lgd.setMargin(0,0,1,1); lgd.setBorder(BlockBorder.NONE); lgd.setBackgroundPaint(TRANSPARENT); BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); Size2D size = lgd.arrange(g2, new RectangleConstraint(new Range(0.0, width * 1.5),new Range(0.0, height))); g2.dispose(); int w = (int) Math.rint(size.width); int h = (int) Math.rint(size.height); BufferedImage img2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g22 = img2.createGraphics(); lgd.draw(g22, new Rectangle2D.Double(0, 0, w, h)); try { ChartUtilities.writeBufferedImageAsPNG(outputStream, img2); }catch (Exception e) { e.printStackTrace(); } finally { g22.dispose(); } } } private static double[] parseData(String data) { String[] parts = data.split(","); double[] values = new double[parts.length]; for (int i = 0; i < parts.length; i++) { if (! parts[i].equals("null")) values[i] = Double.parseDouble(parts[i]); else // no data available. TODO : is it the awaited behaviour ? values[i] = Double.parseDouble("0.0"); } return values; } private static String[] parseLabels(String data) { String[] parts = data.split(","); String[] values = new String[parts.length]; for (int i = 0; i < parts.length; i++) { values[i] = parts[i]; } return values; } }