comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/SQKMChartService.java @ 3274:43e42315ce22

Added service for an overview chart of measuring points in sq relation. flys-artifacts/trunk@4918 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Raimund Renkert <raimund.renkert@intevation.de>
date Tue, 10 Jul 2012 16:37:48 +0000
parents
children 4903e491992e
comparison
equal deleted inserted replaced
3273:739aa90eb79e 3274:43e42315ce22
1 package de.intevation.flys.artifacts.services;
2
3 import de.intevation.artifactdatabase.DefaultService;
4
5 import de.intevation.artifacts.CallMeta;
6 import de.intevation.artifacts.GlobalContext;
7 import de.intevation.artifacts.Service;
8
9 import de.intevation.flys.artifacts.model.FixingsColumn;
10 import de.intevation.flys.artifacts.model.FixingsColumnFactory;
11 import de.intevation.flys.artifacts.model.FixingsFilterBuilder;
12
13 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
14
15 import de.intevation.flys.artifacts.model.SQOverview;
16 import de.intevation.flys.artifacts.model.SQOverviewFactory;
17 import de.intevation.flys.artifacts.model.GaugeFinder;
18 import de.intevation.flys.artifacts.model.GaugeFinderFactory;
19 import de.intevation.flys.artifacts.model.GaugeRange;
20
21 import de.intevation.flys.artifacts.model.fixings.QW;
22
23 import de.intevation.flys.artifacts.resources.Resources;
24
25 import de.intevation.flys.backend.SedDBSessionHolder;
26
27 import de.intevation.flys.jfree.ShapeRenderer;
28
29 import de.intevation.flys.utils.Formatter;
30 import de.intevation.flys.utils.Pair;
31 import de.intevation.flys.utils.KMIndex;
32
33 import java.awt.BasicStroke;
34 import java.awt.Color;
35 import java.awt.Dimension;
36 import java.awt.Transparency;
37
38 import java.awt.geom.Rectangle2D;
39
40 import java.awt.image.BufferedImage;
41
42 import java.io.ByteArrayOutputStream;
43 import java.io.IOException;
44
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Date;
48
49 import javax.imageio.ImageIO;
50
51 import org.apache.log4j.Logger;
52
53 import org.jfree.chart.ChartFactory;
54 import org.jfree.chart.JFreeChart;
55 import org.jfree.chart.LegendItemCollection;
56
57 import org.jfree.chart.axis.DateAxis;
58 import org.jfree.chart.axis.NumberAxis;
59
60 import org.jfree.chart.plot.Marker;
61 import org.jfree.chart.plot.PlotOrientation;
62 import org.jfree.chart.plot.ValueMarker;
63 import org.jfree.chart.plot.XYPlot;
64 import org.jfree.chart.renderer.xy.XYItemRenderer;
65 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
66
67 import org.jfree.data.Range;
68 import org.jfree.data.xy.DefaultXYDataset;
69 import org.jfree.data.xy.XYSeries;
70 import org.jfree.data.xy.XYSeriesCollection;
71
72 import org.jfree.ui.RectangleAnchor;
73 import org.jfree.ui.TextAnchor;
74
75 import org.w3c.dom.Document;
76 import org.w3c.dom.Element;
77 import org.w3c.dom.NodeList;
78
79 public class SQKMChartService
80 extends DefaultService {
81
82 private static final Logger log =
83 Logger.getLogger(FixingsKMChartService.class);
84
85 public static final int DEFAULT_WIDTH = 240;
86 public static final int DEFAULT_HEIGHT = 180;
87
88 public static final String I18N_CHART_LABEL =
89 "sq.km.chart.label";
90
91 public static final String DEFAULT_CHART_LABEL =
92 "Measuring Points";
93
94 public static final String I18N_CHART_TITLE =
95 "sq.km.chart.title";
96
97 public static final String DEFAULT_CHART_TITLE =
98 "Measuring points";
99
100 public static final String I18N_KM_AXIS =
101 "sq.km.chart.km.axis";
102
103 public static final String DEFAULT_KM_AXIS =
104 "km";
105
106 public static final String I18N_DATE_AXIS =
107 "sq.km.chart.date.axis";
108
109 public static final String DEFAULT_DATE_AXIS =
110 "Date";
111
112 public static final String DEFAULT_FORMAT = "png";
113
114 // TODO: Load fancy image from resources.
115 public static final byte [] EMPTY = {
116 (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47,
117 (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a,
118 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d,
119 (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52,
120 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
121 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
122 (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00,
123 (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b,
124 (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00,
125 (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47,
126 (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce,
127 (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00,
128 (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48,
129 (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00,
130 (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00,
131 (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00,
132 (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00,
133 (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74,
134 (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07,
135 (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10,
136 (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77,
137 (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00,
138 (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45,
139 (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f,
140 (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e,
141 (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc,
142 (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00,
143 (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44,
144 (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7,
145 (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00,
146 (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00,
147 (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56,
148 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
149 (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44,
150 (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82
151 };
152
153 private static final Output empty() {
154 return new Output(EMPTY, "image/png");
155 }
156
157 @Override
158 public Service.Output process(
159 Document data,
160 GlobalContext globalContext,
161 CallMeta callMeta
162 ) {
163 log.debug("SQKMChartService.process");
164
165 SedDBSessionHolder.acquire();
166 try {
167 return doProcess(data, globalContext, callMeta);
168 }
169 finally {
170 SedDBSessionHolder.HOLDER.get().close();
171 SedDBSessionHolder.release();
172 }
173 }
174
175 protected Service.Output doProcess(
176 Document input,
177 GlobalContext globalContext,
178 CallMeta callMeta
179 ) {
180 String river = getRiverName(input);
181 Dimension extent = getExtent(input);
182 String format = getFormat(input);
183
184 if (river == null) {
185 log.warn("River invalid.");
186 return empty();
187 }
188
189 SQOverview overview = SQOverviewFactory.getOverview(river);
190
191 if (overview == null) {
192 log.warn("No overview found for river '" + river + "'");
193 return empty();
194 }
195
196 KMIndex<List<Date>> entries = overview.filter(SQOverview.ACCEPT);
197
198 JFreeChart chart = createChart(entries, river, callMeta);
199
200 return encode(chart, extent, format);
201 }
202
203 protected static Output encode(
204 JFreeChart chart,
205 Dimension extent,
206 String format
207 ) {
208 BufferedImage image = chart.createBufferedImage(
209 extent.width, extent.height,
210 Transparency.BITMASK,
211 null);
212
213 ByteArrayOutputStream out = new ByteArrayOutputStream();
214
215 try {
216 ImageIO.write(image, format, out);
217 }
218 catch (IOException ioe) {
219 log.warn("writing image failed", ioe);
220 return empty();
221 }
222
223 return new Output(out.toByteArray(), "image/" + format);
224 }
225
226 protected static JFreeChart createChart(
227 KMIndex<List<Date>> entries,
228 String river,
229 CallMeta callMeta
230 ) {
231
232 XYSeriesCollection dataset = new XYSeriesCollection();
233 String key = Resources.format(
234 callMeta, I18N_CHART_LABEL, DEFAULT_CHART_LABEL, river);
235
236 XYSeries series = new XYSeries(key);
237 for (KMIndex.Entry<List<Date>> e: entries) {
238 double km = e.getKm();
239 List<Date> ds = e.getValue();
240 for (Date d: ds) {
241 series.add(km, d.getTime());
242 }
243 }
244
245 dataset.addSeries(series);
246 String title = Resources.format(
247 callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river);
248
249 String kmAxis = Resources.getMsg(
250 callMeta, I18N_KM_AXIS, DEFAULT_KM_AXIS);
251
252 String dateAxis = Resources.getMsg(
253 callMeta, I18N_DATE_AXIS, DEFAULT_DATE_AXIS);
254
255 JFreeChart chart = ChartFactory.createXYLineChart(
256 title,
257 kmAxis,
258 dateAxis,
259 null,
260 PlotOrientation.VERTICAL,
261 true,
262 true,
263 false);
264
265 XYPlot plot = (XYPlot)chart.getPlot();
266
267 DateAxis dA = new DateAxis();
268 plot.setRangeAxis(dA);
269 plot.setDataset(0, dataset);
270
271 chart.setBackgroundPaint(Color.white);
272 plot.setBackgroundPaint(Color.white);
273 plot.setDomainGridlinePaint(Color.gray);
274 plot.setRangeGridlinePaint(Color.gray);
275 plot.setDomainGridlinesVisible(true);
276 plot.setRangeGridlinesVisible(true);
277 XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
278
279 renderer.setSeriesPaint(0, Color.gray);
280 renderer.setSeriesLinesVisible(0, false);
281 renderer.setSeriesShapesVisible(0, true);
282 renderer.setDrawOutlines(true);
283 return chart;
284 }
285
286
287 protected static String getRiverName(Document input) {
288 NodeList rivers = input.getElementsByTagName("river");
289
290 if (rivers.getLength() == 0) {
291 return null;
292 }
293
294 String river = ((Element)rivers.item(0)).getAttribute("name");
295
296 return river.length() > 0 ? river : null;
297 }
298
299 protected static Dimension getExtent(Document input) {
300
301 int width = DEFAULT_WIDTH;
302 int height = DEFAULT_HEIGHT;
303
304 NodeList extents = input.getElementsByTagName("extent");
305
306 if (extents.getLength() > 0) {
307 Element element = (Element)extents.item(0);
308 String w = element.getAttribute("width");
309 String h = element.getAttribute("height");
310
311 try {
312 width = Math.max(1, Integer.parseInt(w));
313 }
314 catch (NumberFormatException nfe) {
315 log.warn("width '" + w + "' is not a valid.");
316 }
317
318 try {
319 height = Math.max(1, Integer.parseInt(h));
320 }
321 catch (NumberFormatException nfe) {
322 log.warn("height '" + h + "' is not a valid");
323 }
324 }
325
326 return new Dimension(width, height);
327 }
328
329 protected static String getFormat(Document input) {
330 String format = DEFAULT_FORMAT;
331
332 NodeList formats = input.getElementsByTagName("format");
333
334 if (formats.getLength() > 0) {
335 String type = ((Element)formats.item(0)).getAttribute("type");
336 if (type.length() > 0) {
337 format = type;
338 }
339 }
340
341 return format;
342 }
343 }
344 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org