Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java @ 2620:cc0fa1798a3c
FixingsKMChartService: Generate chart and deliver the image as the response of the service.
flys-artifacts/trunk@4205 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 05 Apr 2012 18:07:47 +0000 |
parents | b0597a63fe70 |
children | f0cc556eda29 |
comparison
equal
deleted
inserted
replaced
2619:6ed24efc80de | 2620:cc0fa1798a3c |
---|---|
1 package de.intevation.flys.artifacts.services; | 1 package de.intevation.flys.artifacts.services; |
2 | |
3 import java.util.List; | |
4 | 2 |
5 import de.intevation.artifactdatabase.DefaultService; | 3 import de.intevation.artifactdatabase.DefaultService; |
6 | 4 |
7 import de.intevation.artifacts.CallMeta; | 5 import de.intevation.artifacts.CallMeta; |
8 import de.intevation.artifacts.GlobalContext; | 6 import de.intevation.artifacts.GlobalContext; |
9 import de.intevation.artifacts.Service; | 7 import de.intevation.artifacts.Service; |
10 | 8 |
11 import de.intevation.flys.artifacts.model.FixingsFilterBuilder; | |
12 import de.intevation.flys.artifacts.model.FixingsOverview; | |
13 import de.intevation.flys.artifacts.model.FixingsColumn; | 9 import de.intevation.flys.artifacts.model.FixingsColumn; |
14 import de.intevation.flys.artifacts.model.FixingsColumnFactory; | 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.FixingsOverview; | |
15 import de.intevation.flys.artifacts.model.FixingsOverviewFactory; | 16 import de.intevation.flys.artifacts.model.FixingsOverviewFactory; |
16 | 17 |
17 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; | |
18 | |
19 import de.intevation.flys.backend.SessionHolder; | 18 import de.intevation.flys.backend.SessionHolder; |
20 | 19 |
20 import de.intevation.flys.utils.Pair; | |
21 | |
22 import gnu.trove.TDoubleArrayList; | |
23 | |
24 import java.awt.Dimension; | |
25 import java.awt.Transparency; | |
26 | |
27 import java.awt.image.BufferedImage; | |
28 | |
29 import java.io.ByteArrayOutputStream; | |
30 import java.io.IOException; | |
31 | |
32 import java.util.ArrayList; | |
33 import java.util.List; | |
34 | |
35 import javax.imageio.ImageIO; | |
36 | |
21 import org.apache.log4j.Logger; | 37 import org.apache.log4j.Logger; |
38 | |
39 import org.jfree.chart.ChartFactory; | |
40 import org.jfree.chart.ChartUtilities; | |
41 import org.jfree.chart.JFreeChart; | |
42 | |
43 import org.jfree.chart.plot.PlotOrientation; | |
44 import org.jfree.chart.plot.XYPlot; | |
45 | |
46 import org.jfree.data.xy.DefaultXYDataset; | |
22 | 47 |
23 import org.w3c.dom.Document; | 48 import org.w3c.dom.Document; |
24 import org.w3c.dom.Element; | 49 import org.w3c.dom.Element; |
25 import org.w3c.dom.NodeList; | 50 import org.w3c.dom.NodeList; |
26 | 51 |
28 extends DefaultService | 53 extends DefaultService |
29 { | 54 { |
30 private static final Logger log = | 55 private static final Logger log = |
31 Logger.getLogger(FixingsKMChartService.class); | 56 Logger.getLogger(FixingsKMChartService.class); |
32 | 57 |
58 public static final int DEFAULT_WIDTH = 240; | |
59 public static final int DEFAULT_HEIGHT = 180; | |
60 | |
61 public static final String DEFAULT_FORMAT = "png"; | |
62 | |
63 // TODO: Load fancy image from resources. | |
33 public static final byte [] EMPTY = { | 64 public static final byte [] EMPTY = { |
34 (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, | 65 (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, |
35 (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, | 66 (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, |
36 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, | 67 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, |
37 (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, | 68 (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, |
89 SessionHolder.release(); | 120 SessionHolder.release(); |
90 } | 121 } |
91 } | 122 } |
92 | 123 |
93 protected Service.Output doProcess( | 124 protected Service.Output doProcess( |
94 Document data, | 125 Document input, |
95 GlobalContext globalContext, | 126 GlobalContext globalContext, |
96 CallMeta callMeta | 127 CallMeta callMeta |
97 ) { | 128 ) { |
98 NodeList rivers = data.getElementsByTagName("river"); | 129 String river = getRiverName(input); |
99 NodeList kms = data.getElementsByTagName("km"); | 130 Double km = getKM(input); |
100 | 131 Dimension extent = getExtent(input); |
101 if (rivers.getLength() == 0 || kms.getLength() == 0) { | 132 String format = getFormat(input); |
102 log.warn("Missing river and/or km."); | 133 |
103 return empty(); | 134 if (river == null || km == null) { |
104 } | 135 log.warn("River and/or km invalid."); |
105 | |
106 String river = ((Element)rivers.item(0)).getAttribute("name"); | |
107 String kmS = ((Element)kms .item(0)).getAttribute("value"); | |
108 | |
109 if (river.length() == 0 || kmS.length() == 0) { | |
110 log.warn("River and/or km empty string."); | |
111 return empty(); | |
112 } | |
113 | |
114 double km; | |
115 try { | |
116 km = Double.parseDouble(kmS); | |
117 } | |
118 catch (NumberFormatException nfe) { | |
119 log.warn("Km '" + kmS + " is not a valid number."); | |
120 return empty(); | 136 return empty(); |
121 } | 137 } |
122 | 138 |
123 FixingsOverview overview = FixingsOverviewFactory.getOverview(river); | 139 FixingsOverview overview = FixingsOverviewFactory.getOverview(river); |
124 | 140 |
125 if (overview == null) { | 141 if (overview == null) { |
126 log.warn("No overview found for river '" + river + "'"); | 142 log.warn("No overview found for river '" + river + "'"); |
127 return empty(); | 143 return empty(); |
128 } | 144 } |
129 | 145 |
130 FixingsFilterBuilder ffb = new FixingsFilterBuilder(data); | 146 FixingsFilterBuilder ffb = new FixingsFilterBuilder(input); |
131 | 147 |
132 List<Fixing.Column> columns = overview.filter( | 148 List<Fixing.Column> columns = overview.filter( |
133 ffb.getRange(), | 149 ffb.getRange(), |
134 ffb.getFilter()); | 150 ffb.getFilter()); |
135 | 151 |
136 for (Fixing.Column column: columns) { | 152 List<Pair<Fixing.Column, FixingsColumn>> cols = |
137 FixingsColumn columnData = | 153 new ArrayList<Pair<Fixing.Column, FixingsColumn>>(); |
138 FixingsColumnFactory.INSTANCE.getColumnData(column); | 154 |
139 if (columnData == null) { | 155 for (Fixing.Column col: columns) { |
140 continue; | 156 FixingsColumn data = |
141 } | 157 FixingsColumnFactory.INSTANCE.getColumnData(col); |
142 } | 158 if (data != null) { |
143 // TODO: Implement chart generation! | 159 cols.add(new Pair<Fixing.Column, FixingsColumn>(col, data)); |
144 | 160 } |
145 return empty(); | 161 } |
162 | |
163 JFreeChart chart = createChart(cols, river, km); | |
164 | |
165 return encode(chart, extent, format); | |
166 } | |
167 | |
168 protected static Output encode( | |
169 JFreeChart chart, | |
170 Dimension extent, | |
171 String format | |
172 ) { | |
173 BufferedImage image = chart.createBufferedImage( | |
174 extent.width, extent.height, | |
175 Transparency.BITMASK, | |
176 null); | |
177 | |
178 ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
179 | |
180 try { | |
181 ImageIO.write(image, format, out); | |
182 } | |
183 catch (IOException ioe) { | |
184 log.warn("writing image failed", ioe); | |
185 return empty(); | |
186 } | |
187 | |
188 return new Output(out.toByteArray(), "image/" + format); | |
189 } | |
190 | |
191 protected static JFreeChart createChart( | |
192 List<Pair<Fixing.Column, FixingsColumn>> cols, | |
193 String river, | |
194 double km | |
195 ) { | |
196 | |
197 TDoubleArrayList ws = new TDoubleArrayList(cols.size()); | |
198 TDoubleArrayList qs = new TDoubleArrayList(cols.size()); | |
199 | |
200 double [] w = new double[1]; | |
201 for (Pair<Fixing.Column, FixingsColumn> col: cols) { | |
202 boolean interpolated = col.getB().getW(km, w); | |
203 // TODO: Do something special with the interpolated values. | |
204 double q = col.getB().getQ(km); | |
205 if (!Double.isNaN(w[0]) && !Double.isNaN(q)) { | |
206 ws.add(w[0]); | |
207 qs.add(q); | |
208 // TODO: Generate labels depending on sectors. | |
209 } | |
210 } | |
211 | |
212 DefaultXYDataset dataset = new DefaultXYDataset(); | |
213 | |
214 dataset.addSeries( | |
215 "Fixierungen", // TODO: i18n | |
216 new double [][] { ws.toNativeArray(), qs.toNativeArray() }); | |
217 | |
218 JFreeChart chart = ChartFactory.createXYLineChart( | |
219 "Fixierungen " + river + ": km " + km, // TODO: i18n | |
220 "Q", // TODO: i18n | |
221 "W", // TODO: i18n | |
222 null, | |
223 PlotOrientation.VERTICAL, | |
224 true, | |
225 true, | |
226 false); | |
227 | |
228 XYPlot plot = chart.getXYPlot(); | |
229 | |
230 plot.setDataset(dataset); | |
231 | |
232 ChartUtilities.applyCurrentTheme(chart); | |
233 | |
234 return chart; | |
235 } | |
236 | |
237 protected static String getRiverName(Document input) { | |
238 NodeList rivers = input.getElementsByTagName("river"); | |
239 | |
240 if (rivers.getLength() == 0) { | |
241 return null; | |
242 } | |
243 | |
244 String river = ((Element)rivers.item(0)).getAttribute("name"); | |
245 | |
246 return river.length() == 0 ? river : null; | |
247 } | |
248 | |
249 protected static Double getKM(Document input) { | |
250 NodeList kms = input.getElementsByTagName("km"); | |
251 | |
252 if (kms.getLength() == 0) { | |
253 return null; | |
254 } | |
255 | |
256 String km = ((Element)kms.item(0)).getAttribute("value"); | |
257 | |
258 try { | |
259 return Double.valueOf(km); | |
260 } | |
261 catch (NumberFormatException nfe) { | |
262 log.warn("Km '" + km + " is not a valid number."); | |
263 return null; | |
264 } | |
265 } | |
266 | |
267 protected static Dimension getExtent(Document input) { | |
268 | |
269 int width = DEFAULT_WIDTH; | |
270 int height = DEFAULT_HEIGHT; | |
271 | |
272 NodeList extents = input.getElementsByTagName("extent"); | |
273 | |
274 if (extents.getLength() > 0) { | |
275 Element element = (Element)extents.item(0); | |
276 String w = element.getAttribute("width"); | |
277 String h = element.getAttribute("height"); | |
278 | |
279 try { | |
280 width = Math.max(1, Integer.parseInt(w)); | |
281 } | |
282 catch (NumberFormatException nfe) { | |
283 log.warn("width '" + w + "' is not a valid."); | |
284 } | |
285 | |
286 try { | |
287 height = Math.max(1, Integer.parseInt(h)); | |
288 } | |
289 catch (NumberFormatException nfe) { | |
290 log.warn("height '" + h + "' is not a valid"); | |
291 } | |
292 } | |
293 | |
294 return new Dimension(width, height); | |
295 } | |
296 | |
297 protected static String getFormat(Document input) { | |
298 String format = DEFAULT_FORMAT; | |
299 | |
300 NodeList formats = input.getElementsByTagName("format"); | |
301 | |
302 if (formats.getLength() > 0) { | |
303 String type = ((Element)formats.item(0)).getAttribute("type"); | |
304 if (type.length() > 0) { | |
305 format = type; | |
306 } | |
307 } | |
308 | |
309 return format; | |
146 } | 310 } |
147 } | 311 } |
148 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 312 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |