comparison artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java@bd047b71ab37
children 36404dc7fea0
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 /*
2 * Copyright (c) 2011 by Intevation GmbH
3 *
4 * This program is free software under the LGPL (>=v2.1)
5 * Read the file LGPL.txt coming with the software for details
6 * or visit http://www.gnu.org/licenses/ if it does not exist.
7 */
8 package org.dive4elements.river.exports;
9
10 import com.lowagie.text.Document;
11 import com.lowagie.text.DocumentException;
12 import com.lowagie.text.PageSize;
13 import com.lowagie.text.Rectangle;
14
15 import com.lowagie.text.pdf.PdfContentByte;
16 import com.lowagie.text.pdf.PdfTemplate;
17 import com.lowagie.text.pdf.PdfWriter;
18
19 import java.awt.Graphics2D;
20 import java.awt.Transparency;
21
22 import java.awt.geom.Rectangle2D.Double;
23
24 import java.awt.geom.Rectangle2D;
25
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.UnsupportedEncodingException;
30 import org.jfree.chart.ChartRenderingInfo;
31
32 import javax.imageio.ImageIO;
33
34 import au.com.bytecode.opencsv.CSVWriter;
35
36 import org.apache.batik.svggen.SVGGraphics2D;
37 import org.apache.batik.svggen.SVGGraphics2DIOException;
38
39 import org.apache.log4j.Logger;
40
41 import org.jfree.chart.JFreeChart;
42 import org.jfree.chart.plot.XYPlot;
43 import org.jfree.data.xy.XYDataset;
44
45 import org.dive4elements.artifacts.CallContext;
46
47 import org.dive4elements.artifacts.common.utils.XMLUtils;
48
49
50 /**
51 * This class is a helper class which supports some methods to export charts
52 * into specific formats.
53 *
54 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
55 */
56 public class ChartExportHelper {
57
58 public static final String FORMAT_PNG = "png";
59
60 public static final String FORMAT_PDF = "pdf";
61
62 public static final String FORMAT_SVG = "svg";
63
64 public static final String FORMAT_CSV = "csv";
65
66 /**
67 * Constant field to define A4 as default page size.
68 */
69 public static final String DEFAULT_PAGE_SIZE = "A4";
70
71 /**
72 * Constant field to define UTF-8 as default encoding.
73 */
74 public static final String DEFAULT_ENCODING = "UTF-8";
75
76 /** The default separator for the CSV export. */
77 public static final char DEFAULT_CSV_SEPARATOR = ',';
78
79
80 /**
81 * Logger used for logging with log4j.
82 */
83 private static Logger log = Logger.getLogger(ChartExportHelper.class);
84
85
86 /**
87 * A method to export a <code>JFreeChart</code> as image to an
88 * <code>OutputStream</code> with a given format, width and height.
89 *
90 * @param out OutputStream
91 * @param chart JFreeChart object to be exported.
92 * @param cc context, in which e.g. size is stored.
93 *
94 * @throws IOException if writing image to OutputStream failed.
95 */
96 public static void exportImage(
97 OutputStream out,
98 JFreeChart chart,
99 CallContext cc
100 )
101 throws IOException
102 {
103 log.info("export chart as png");
104
105 ChartRenderingInfo info = new ChartRenderingInfo();
106
107 String format = (String) cc.getContextValue("chart.image.format");
108
109 int[] size = getSize(cc);
110
111 ImageIO.write(
112 chart.createBufferedImage(
113 size[0], size[1], Transparency.BITMASK, info
114 ),
115 format,
116 out
117 );
118 }
119
120
121 /**
122 * A method to export a <code>JFreeChart</code> as SVG to an
123 * <code>OutputStream</code>.
124 *
125 * @param out OutputStream
126 * @param chart JFreeChart to be exported
127 * @param context The CallContext object that contains extra chart
128 * parameters.
129 */
130 public static void exportSVG(
131 OutputStream out,
132 JFreeChart chart,
133 CallContext context
134 ) {
135 String encoding = (String) context.getContextValue("chart.encoding");
136
137 log.info("export chart as svg");
138
139 if (encoding == null)
140 encoding = DEFAULT_ENCODING;
141
142 org.w3c.dom.Document document = XMLUtils.newDocument();
143 SVGGraphics2D graphics = new SVGGraphics2D(document);
144
145 int[] size = getSize(context);
146
147 ChartRenderingInfo info = new ChartRenderingInfo();
148
149 chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,size[0],size[1]), info);
150
151 try {
152 graphics.stream(new OutputStreamWriter(out, encoding));
153 }
154 catch (SVGGraphics2DIOException svge) {
155 log.error("Error while writing svg export to output stream.", svge);
156 }
157 catch (UnsupportedEncodingException uee) {
158 log.error("Unsupported encoding: " + encoding, uee);
159 }
160 }
161
162
163 /**
164 * A method to export a <code>JFreeChart</code> as PDF to an
165 * <code>OutputStream</code>.
166 *
167 * @param out OutputStream
168 * @param chart JFreeChart
169 */
170 public static void exportPDF(
171 OutputStream out,
172 JFreeChart chart,
173 CallContext cc
174 ) {
175 log.info("export chart as pdf.");
176
177 String pageFormat = (String) cc.getContextValue("chart.page.format");
178
179 if (pageFormat == null)
180 pageFormat = DEFAULT_PAGE_SIZE;
181
182 // Max size of the chart.
183 Rectangle page = PageSize.getRectangle(pageFormat);
184 float pageWidth = page.getWidth();
185 float pageHeight = page.getHeight();
186
187 // The chart width.
188 int[] size = getSize(cc);
189
190 boolean landscape = size[0] > size[1];
191
192 float width = 0;
193 float height = 0;
194 if (landscape) {
195 width = pageHeight;
196 height = pageWidth;
197 }
198 else {
199 width = pageWidth;
200 height = pageHeight;
201 }
202
203 float marginLeft = (Float) cc.getContextValue(
204 "chart.marginLeft");
205
206 float marginRight = (Float) cc.getContextValue(
207 "chart.marginRight");
208
209 float marginTop = (Float) cc.getContextValue(
210 "chart.marginTop");
211
212 float marginBottom = (Float) cc.getContextValue(
213 "chart.marginBottom");
214
215 float spaceX = width - marginLeft - marginRight;
216 if (size[0] > spaceX) {
217 log.warn("Width of the chart is too big for pdf -> resize it now.");
218 double ratio = ((double)spaceX) / size[0];
219 size[0] *= ratio;
220 size[1] *= ratio;
221 log.debug("Resized chart to " + size[0] + "x" + size[1]);
222 }
223
224 float spaceY = height - marginTop - marginBottom;
225 if (size[1] > spaceY) {
226 log.warn("Height of the chart is too big for pdf -> resize it now.");
227 double ratio = ((double)spaceY) / size[1];
228 size[0] *= ratio;
229 size[1] *= ratio;
230 log.debug("Resized chart to " + size[0] + "x" + size[1]);
231 }
232
233 Document document = null;
234 if (landscape) {
235 document = new Document(page.rotate());
236 log.debug("Create landscape pdf.");
237 }
238 else
239 document = new Document(page);
240
241 try {
242 PdfWriter writer = PdfWriter.getInstance(document, out);
243
244 document.addSubject(chart.getTitle().getText());
245 document.addCreationDate();
246 document.open();
247
248 PdfContentByte content = writer.getDirectContent();
249
250 PdfTemplate template = content.createTemplate(width, height);
251 Graphics2D graphics = template.createGraphics(width, height);
252
253 double[] origin = getCenteredAnchor(
254 marginLeft, marginRight, marginBottom, marginTop,
255 width, height,
256 size[0], size[1]);
257
258 Rectangle2D area = new Rectangle2D.Double(
259 origin[0], origin[1], size[0], size[1]);
260
261 ChartRenderingInfo info = new ChartRenderingInfo();
262
263 chart.draw(graphics, area, info);
264 graphics.dispose();
265 content.addTemplate(template, 0f, 0f);
266 }
267 catch (DocumentException de) {
268 log.error("Error while exporting chart to pdf.", de);
269 }
270 finally {
271 document.close();
272 }
273 }
274
275
276 /**
277 * A method to export a CSV file to an
278 * <code>OutputStream</code>.
279 *
280 * @param out OutputStream
281 * @param chart JFreeChart containing the data.
282 * @param context The CallContext object that contains extra parameters.
283 */
284 public static void exportCSV(
285 OutputStream out,
286 JFreeChart chart,
287 CallContext context)
288 {
289 log.debug("export chart as CSV");
290 CSVWriter writer = null;
291 try {
292 writer = new CSVWriter(
293 new OutputStreamWriter(
294 out,
295 DEFAULT_ENCODING),
296 DEFAULT_CSV_SEPARATOR);
297 }
298 catch(UnsupportedEncodingException uee) {
299 log.warn("Wrong encoding for CSV export.");
300 return;
301 }
302 XYPlot plot = chart.getXYPlot();
303 int count = plot.getDatasetCount();
304 for (int i = 0; i < count; i++) {
305 XYDataset data = plot.getDataset(i);
306 int scount = data.getSeriesCount();
307 for (int j = 0; j < scount; j++) {
308 Comparable seriesKey = data.getSeriesKey(j);
309 log.debug("series key: " + seriesKey.toString());
310 writeCSVHeader(writer, seriesKey.toString());
311 writeCSVData(writer, data);
312 }
313 }
314 try {
315 writer.close();
316 }
317 catch(IOException ioe) {
318 log.error("Writing CSV export failed!");
319 }
320 }
321
322
323 protected static void writeCSVHeader(CSVWriter writer, String key) {
324 writer.writeNext(new String[] {"#"});
325 writer.writeNext(new String[] {"# " + key});
326 writer.writeNext(new String[] {"#"});
327 writer.writeNext(new String[] {"X", "Y"});
328 }
329
330
331 protected static void writeCSVData(CSVWriter writer, XYDataset data) {
332 int series = data.getSeriesCount();
333 for (int i = 0; i < series; i++) {
334 int items = data.getItemCount(i);
335 for (int j = 0; j < items; j++) {
336 log.debug("write data: " + data.getX(i, j) + ", " + data.getY(i, j));
337 writer.writeNext(new String[] {
338 data.getX(i, j).toString(),
339 data.getY(i, j).toString()});
340 }
341 }
342 }
343
344
345 public static int[] getSize(CallContext cc) {
346 int[] size = new int[2];
347
348 size[0] = (Integer) cc.getContextValue("chart.width");
349 size[1] = (Integer) cc.getContextValue("chart.height");
350
351 return size;
352 }
353
354
355 /**
356 * This method returns the anchor of the chart so that the chart is centered
357 * according to the given parameters.
358 *
359 * @param mLeft Left margin
360 * @param mRight Right margin
361 * @param mBottom Bottom margin
362 * @param mTop Top margin
363 * @param width The complete width of the drawing area.
364 * @param height The complete height of the drawing area.
365 * @param chartWidth The width of the chart.
366 * @param chartHeight The height of the chart.
367 *
368 * @return an array that contains the anchor for a chart with the given
369 * parameters. The first value is the x point, the second value is the y
370 * point.
371 */
372 public static double[] getCenteredAnchor(
373 double mLeft, double mRight, double mBottom, double mTop,
374 double width, double height,
375 double chartWidth, double chartHeight
376 ) {
377 if (log.isDebugEnabled()) {
378 log.debug("Calculate centered origin...");
379 log.debug("-> PDF width : " + width);
380 log.debug("-> PDF height : " + height);
381 log.debug("-> Chart width : " + chartWidth);
382 log.debug("-> Chart height : " + chartHeight);
383 log.debug("-> margin left : " + mLeft);
384 log.debug("-> margin right : " + mRight);
385 log.debug("-> margin bottom: " + mBottom);
386 log.debug("-> margin top : " + mTop);
387 }
388
389 double[] origin = new double[2];
390
391 double centerX = width / 2;
392 double centerY = height / 2;
393
394 origin[0] = centerX - chartWidth / 2;
395 origin[1] = centerY - chartHeight / 2;
396
397 origin[0] = origin[0] >= mLeft ? origin[0] : mLeft;
398 origin[1] = origin[1] >= mTop ? origin[1] : mTop;
399
400 if (log.isDebugEnabled()) {
401 log.debug("==> centered left origin: " + origin[0]);
402 log.debug("==> centered top origin: " + origin[1]);
403 }
404
405 return origin;
406 }
407 }
408 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org