Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.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/WaterlevelExporter.java@bd047b71ab37 |
children | 4897a58c8746 |
comparison
equal
deleted
inserted
replaced
5837:d9901a08d0a6 | 5838:5aa05a7a34b7 |
---|---|
1 package org.dive4elements.river.exports; | |
2 | |
3 import java.io.IOException; | |
4 import java.io.OutputStream; | |
5 import java.text.DateFormat; | |
6 import java.text.NumberFormat; | |
7 import java.util.ArrayList; | |
8 import java.util.Map; | |
9 import java.util.HashMap; | |
10 import java.util.Date; | |
11 import java.util.List; | |
12 import java.util.Locale; | |
13 import java.util.regex.Matcher; | |
14 import java.util.regex.Pattern; | |
15 | |
16 import org.w3c.dom.Document; | |
17 | |
18 import org.apache.log4j.Logger; | |
19 | |
20 import au.com.bytecode.opencsv.CSVWriter; | |
21 | |
22 import org.dive4elements.river.artifacts.model.ConstantWQKms; | |
23 | |
24 import net.sf.jasperreports.engine.JasperExportManager; | |
25 import net.sf.jasperreports.engine.JasperFillManager; | |
26 import net.sf.jasperreports.engine.JasperPrint; | |
27 import net.sf.jasperreports.engine.JRException; | |
28 | |
29 import org.dive4elements.artifacts.CallContext; | |
30 import org.dive4elements.artifacts.CallMeta; | |
31 import org.dive4elements.artifacts.common.utils.Config; | |
32 | |
33 import org.dive4elements.river.model.Gauge; | |
34 | |
35 import org.dive4elements.river.artifacts.access.FixRealizingAccess; | |
36 import org.dive4elements.river.artifacts.access.RangeAccess; | |
37 import org.dive4elements.river.artifacts.FixationArtifact; | |
38 import org.dive4elements.river.artifacts.FLYSArtifact; | |
39 import org.dive4elements.river.artifacts.WINFOArtifact; | |
40 import org.dive4elements.river.artifacts.model.CalculationResult; | |
41 import org.dive4elements.river.artifacts.model.Segment; | |
42 import org.dive4elements.river.artifacts.model.WQCKms; | |
43 import org.dive4elements.river.artifacts.model.WQKms; | |
44 import org.dive4elements.river.artifacts.model.WKmsJRDataSource; | |
45 import org.dive4elements.river.artifacts.model.WQKmsResult; | |
46 import org.dive4elements.river.artifacts.resources.Resources; | |
47 | |
48 import org.dive4elements.river.utils.FLYSUtils; | |
49 import org.dive4elements.river.utils.FLYSUtils.WQ_MODE; | |
50 import org.dive4elements.river.utils.Formatter; | |
51 | |
52 /** | |
53 * Generates different output formats (wst, csv, pdf) of data that resulted from | |
54 * a waterlevel computation. | |
55 * | |
56 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
57 */ | |
58 public class WaterlevelExporter extends AbstractExporter { | |
59 | |
60 /** The logger used in this exporter.*/ | |
61 private static Logger logger = Logger.getLogger(WaterlevelExporter.class); | |
62 | |
63 public static final String FACET_WST = "wst"; | |
64 | |
65 public static final String CSV_KM_HEADER = | |
66 "export.waterlevel.csv.header.km"; | |
67 | |
68 public static final String CSV_W_HEADER = | |
69 "export.waterlevel.csv.header.w"; | |
70 | |
71 public static final String CSV_Q_HEADER = | |
72 "export.waterlevel.csv.header.q"; | |
73 | |
74 public static final String CSV_Q_DESC_HEADER = | |
75 "export.waterlevel.csv.header.q.desc"; | |
76 | |
77 public static final String CSV_W_DESC_HEADER = | |
78 "export.waterlevel.csv.header.w.desc"; | |
79 | |
80 public static final String CSV_LOCATION_HEADER = | |
81 "export.waterlevel.csv.header.location"; | |
82 | |
83 public static final String CSV_GAUGE_HEADER = | |
84 "export.waterlevel.csv.header.gauge"; | |
85 | |
86 public static final String CSV_META_RESULT = | |
87 "export.waterlevel.csv.meta.result"; | |
88 | |
89 public static final String CSV_META_CREATION = | |
90 "export.waterlevel.csv.meta.creation"; | |
91 | |
92 public static final String CSV_META_CALCULATIONBASE = | |
93 "export.waterlevel.csv.meta.calculationbase"; | |
94 | |
95 public static final String CSV_META_RIVER = | |
96 "export.waterlevel.csv.meta.river"; | |
97 | |
98 public static final String CSV_META_RANGE = | |
99 "export.waterlevel.csv.meta.range"; | |
100 | |
101 public static final String CSV_META_GAUGE = | |
102 "export.waterlevel.csv.meta.gauge"; | |
103 | |
104 public static final String CSV_META_Q = | |
105 "export.waterlevel.csv.meta.q"; | |
106 | |
107 public static final String CSV_META_W = | |
108 "export.waterlevel.csv.meta.w"; | |
109 | |
110 public static final String CSV_NOT_IN_GAUGE_RANGE = | |
111 "export.waterlevel.csv.not.in.gauge.range"; | |
112 | |
113 public static final Pattern NUMBERS_PATTERN = | |
114 Pattern.compile("\\D*(\\d++.\\d*)\\D*"); | |
115 | |
116 public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; | |
117 public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; | |
118 public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; | |
119 public static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung"; | |
120 public static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]"; | |
121 public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; | |
122 public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel"; | |
123 public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = | |
124 "außerhalb des gewählten Bezugspegels"; | |
125 | |
126 public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode"; | |
127 public static final String JASPER_FILE = "export.waterlevel.pdf.file"; | |
128 | |
129 /** The storage that contains all WQKms objects for the different facets.*/ | |
130 protected List<WQKms[]> data; | |
131 | |
132 | |
133 public void init(Document request, OutputStream out, CallContext context) { | |
134 logger.debug("WaterlevelExporter.init"); | |
135 | |
136 super.init(request, out, context); | |
137 | |
138 this.data = new ArrayList<WQKms[]>(); | |
139 } | |
140 | |
141 | |
142 @Override | |
143 public void generate() | |
144 throws IOException | |
145 { | |
146 logger.debug("WaterlevelExporter.generate"); | |
147 | |
148 if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { | |
149 generateCSV(); | |
150 } | |
151 else if (facet != null && facet.equals(FACET_WST)) { | |
152 generateWST(); | |
153 } | |
154 else if (facet != null && facet.equals(AbstractExporter.FACET_PDF)) { | |
155 generatePDF(); | |
156 } | |
157 else { | |
158 throw new IOException("invalid facet for exporter"); | |
159 } | |
160 } | |
161 | |
162 | |
163 @Override | |
164 protected void addData(Object d) { | |
165 if (d instanceof CalculationResult) { | |
166 d = ((CalculationResult)d).getData(); | |
167 if (d instanceof WQKms []) { | |
168 data.add((WQKms [])d); | |
169 } | |
170 else if (d instanceof WQKmsResult) { | |
171 data.add(((WQKmsResult) d).getWQKms()); | |
172 } | |
173 } | |
174 } | |
175 | |
176 | |
177 /** | |
178 * This method is used to prepare the column titles of waterlevel exports. | |
179 * Titles in this export include the Q value. If a Q value matches a named | |
180 * main value (as HQ100 or MNQ) this named main value should be used as | |
181 * title. This method resets the name of the <i>wqkms</i> object if such | |
182 * named main value fits to the chosen Q. | |
183 * | |
184 * @param winfo A WINFO Artifact. | |
185 * @param wqkms A WQKms object that should be prepared. | |
186 */ | |
187 protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) { | |
188 logger.debug("WaterlevelExporter.getColumnTitle"); | |
189 | |
190 String name = wqkms.getName(); | |
191 | |
192 logger.debug("Name of WQKms = '" + name + "'"); | |
193 | |
194 if (name.indexOf("W=") >= 0) { | |
195 return name; | |
196 } | |
197 | |
198 Matcher m = NUMBERS_PATTERN.matcher(name); | |
199 | |
200 if (m.matches()) { | |
201 String raw = m.group(1); | |
202 | |
203 try { | |
204 double v = Double.valueOf(raw); | |
205 | |
206 String nmv = FLYSUtils.getNamedMainValue(winfo, v); | |
207 | |
208 if (nmv != null && nmv.length() > 0) { | |
209 nmv = FLYSUtils.stripNamedMainValue(nmv); | |
210 nmv += "=" + String.valueOf(v); | |
211 logger.debug("Set named main value '" + nmv + "'"); | |
212 | |
213 return nmv; | |
214 } | |
215 } | |
216 catch (NumberFormatException nfe) { | |
217 // do nothing here | |
218 } | |
219 } | |
220 | |
221 return name; | |
222 } | |
223 | |
224 | |
225 protected String getCSVRowTitle(WINFOArtifact winfo, WQKms wqkms) { | |
226 logger.debug("WaterlevelExporter.prepareNamedValue"); | |
227 | |
228 String name = wqkms.getName(); | |
229 | |
230 logger.debug("Name of WQKms = '" + name + "'"); | |
231 | |
232 WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); | |
233 | |
234 if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.QGAUGE) { | |
235 return localizeWQKms(winfo, wqkms); | |
236 } | |
237 | |
238 Double v = wqkms.getRawValue(); | |
239 | |
240 String nmv = FLYSUtils.getNamedMainValue(winfo, v); | |
241 | |
242 if (nmv != null && nmv.length() > 0) { | |
243 nmv = FLYSUtils.stripNamedMainValue(nmv); | |
244 logger.debug("Set named main value '" + nmv + "'"); | |
245 | |
246 return nmv; | |
247 } | |
248 | |
249 return localizeWQKms(winfo, wqkms); | |
250 } | |
251 | |
252 | |
253 /** | |
254 * Get a string like 'W=' or 'Q=' with a number following in localized | |
255 * format. | |
256 */ | |
257 protected String localizeWQKms(WINFOArtifact winfo, WQKms wqkms) { | |
258 WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); | |
259 Double rawValue = wqkms.getRawValue(); | |
260 | |
261 if (rawValue == null) { | |
262 return wqkms.getName(); | |
263 } | |
264 | |
265 NumberFormat nf = Formatter.getRawFormatter(context); | |
266 | |
267 if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.WGAUGE) { | |
268 return "W=" + nf.format(rawValue); | |
269 } | |
270 else { | |
271 return "Q=" + nf.format(rawValue); | |
272 } | |
273 } | |
274 | |
275 | |
276 @Override | |
277 protected void writeCSVData(CSVWriter writer) { | |
278 logger.info("WaterlevelExporter.writeData"); | |
279 | |
280 WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); | |
281 boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; | |
282 boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; | |
283 FLYSUtils.WQ_INPUT input | |
284 = FLYSUtils.getWQInputMode((FLYSArtifact)master); | |
285 | |
286 writeCSVMeta(writer); | |
287 writeCSVHeader(writer, atGauge, isQ); | |
288 | |
289 for (WQKms[] tmp: data) { | |
290 for (WQKms wqkms: tmp) { | |
291 wQKms2CSV(writer, wqkms, atGauge, isQ); | |
292 } | |
293 } | |
294 } | |
295 | |
296 | |
297 protected void writeCSVMeta(CSVWriter writer) { | |
298 logger.info("WaterlevelExporter.writeCSVMeta"); | |
299 | |
300 // TODO use Access instead of FLYSUtils | |
301 | |
302 CallMeta meta = context.getMeta(); | |
303 | |
304 FLYSArtifact flys = (FLYSArtifact) master; | |
305 | |
306 writer.writeNext(new String[] { | |
307 Resources.getMsg( | |
308 meta, | |
309 CSV_META_RESULT, | |
310 CSV_META_RESULT, | |
311 new Object[] { FLYSUtils.getRivername(flys) }) | |
312 }); | |
313 | |
314 Locale locale = Resources.getLocale(meta); | |
315 DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); | |
316 | |
317 writer.writeNext(new String[] { | |
318 Resources.getMsg( | |
319 meta, | |
320 CSV_META_CREATION, | |
321 CSV_META_CREATION, | |
322 new Object[] { df.format(new Date()) }) | |
323 }); | |
324 | |
325 writer.writeNext(new String[] { | |
326 Resources.getMsg( | |
327 meta, | |
328 CSV_META_CALCULATIONBASE, | |
329 CSV_META_CALCULATIONBASE, | |
330 new Object[] { "" }) // TODO what is required at this place? | |
331 }); | |
332 | |
333 writer.writeNext(new String[] { | |
334 Resources.getMsg( | |
335 meta, | |
336 CSV_META_RIVER, | |
337 CSV_META_RIVER, | |
338 new Object[] { FLYSUtils.getRivername(flys) }) | |
339 }); | |
340 | |
341 RangeAccess rangeAccess = new RangeAccess(flys, null); | |
342 double[] kms = rangeAccess.getKmRange(); | |
343 writer.writeNext(new String[] { | |
344 Resources.getMsg( | |
345 meta, | |
346 CSV_META_RANGE, | |
347 CSV_META_RANGE, | |
348 new Object[] { kms[0], kms[kms.length-1] }) | |
349 }); | |
350 | |
351 writer.writeNext(new String[] { | |
352 Resources.getMsg( | |
353 meta, | |
354 CSV_META_GAUGE, | |
355 CSV_META_GAUGE, | |
356 new Object[] { FLYSUtils.getGaugename(flys) }) | |
357 }); | |
358 | |
359 FLYSUtils.WQ_MODE wq = FLYSUtils.getWQMode(flys); | |
360 if (wq == FLYSUtils.WQ_MODE.QFREE || wq == FLYSUtils.WQ_MODE.QGAUGE) { | |
361 double[] qs = FLYSUtils.getQs(flys); | |
362 FLYSUtils.WQ_INPUT input = FLYSUtils.getWQInputMode(flys); | |
363 | |
364 String data = ""; | |
365 | |
366 if ((input == FLYSUtils.WQ_INPUT.ADAPTED || | |
367 input == FLYSUtils.WQ_INPUT.RANGE) && | |
368 qs != null && qs.length > 0) | |
369 { | |
370 data = String.valueOf(qs[0]); | |
371 data += " - " + String.valueOf(qs[qs.length-1]); | |
372 } | |
373 else if (input == FLYSUtils.WQ_INPUT.SINGLE && qs != null){ | |
374 data = String.valueOf(qs[0]); | |
375 for (int i = 1; i < qs.length; i++) { | |
376 data += ", " + String.valueOf(qs[i]); | |
377 } | |
378 } | |
379 else { | |
380 logger.warn("Could not determine Q range!"); | |
381 } | |
382 | |
383 writer.writeNext(new String[] { | |
384 Resources.getMsg( | |
385 meta, | |
386 CSV_META_Q, | |
387 CSV_META_Q, | |
388 new Object[] {data}) | |
389 }); | |
390 } | |
391 else { | |
392 double[] ws = FLYSUtils.getWs(flys); | |
393 | |
394 String lower = ""; | |
395 String upper = ""; | |
396 | |
397 if (ws != null && ws.length > 0) { | |
398 lower = String.valueOf(ws[0]); | |
399 upper = String.valueOf(ws[ws.length-1]); | |
400 } | |
401 else { | |
402 logger.warn("Could not determine W range!"); | |
403 } | |
404 | |
405 writer.writeNext(new String[] { | |
406 Resources.getMsg( | |
407 meta, | |
408 CSV_META_W, | |
409 CSV_META_W, | |
410 new Object[] { lower, upper }) | |
411 }); | |
412 } | |
413 | |
414 writer.writeNext(new String[] { "" }); | |
415 } | |
416 | |
417 | |
418 /** | |
419 * Write the header, with different headings depending on whether at a | |
420 * gauge or at a location. | |
421 */ | |
422 protected void writeCSVHeader( | |
423 CSVWriter writer, | |
424 boolean atGauge, | |
425 boolean isQ | |
426 ) { | |
427 logger.info("WaterlevelExporter.writeCSVHeader"); | |
428 | |
429 String unit = FLYSUtils.getRiver((FLYSArtifact) master).getWstUnit().getName(); | |
430 | |
431 if (atGauge) { | |
432 writer.writeNext(new String[] { | |
433 msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), | |
434 msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), | |
435 msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), | |
436 (isQ | |
437 ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) | |
438 : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)), | |
439 msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), | |
440 msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) | |
441 }); | |
442 } | |
443 else { | |
444 writer.writeNext(new String[] { | |
445 msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), | |
446 // TODO flys/issue1128 (unit per river) | |
447 msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), | |
448 msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), | |
449 msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) | |
450 }); | |
451 } | |
452 } | |
453 | |
454 | |
455 /** Linearly search for gauge which is valid at km. */ | |
456 private static Gauge findGauge(double km, List<Gauge> gauges) { | |
457 for (Gauge gauge: gauges) { | |
458 if (gauge.getRange().contains(km)) { | |
459 return gauge; | |
460 } | |
461 } | |
462 return null; | |
463 } | |
464 | |
465 private static Segment findSegment(double km, List<Segment> segments) { | |
466 for (Segment segment: segments) { | |
467 if (segment.inside(km)) { | |
468 return segment; | |
469 } | |
470 } | |
471 return null; | |
472 } | |
473 | |
474 | |
475 private void writeRow4(CSVWriter writer, double wqkm[], FLYSArtifact flys) { | |
476 NumberFormat kmf = getKmFormatter(); | |
477 NumberFormat wf = getWFormatter(); | |
478 NumberFormat qf = getQFormatter(); | |
479 | |
480 writer.writeNext(new String[] { | |
481 kmf.format(wqkm[2]), | |
482 wf.format(wqkm[0]), | |
483 qf.format(wqkm[1]), | |
484 FLYSUtils.getLocationDescription(flys, wqkm[2]) | |
485 }); | |
486 } | |
487 | |
488 | |
489 /** Write an csv-row at gauge location. */ | |
490 private void writeRow6(CSVWriter writer, double wqkm[], String wOrQDesc, | |
491 FLYSArtifact flys, String gaugeName) { | |
492 NumberFormat kmf = getKmFormatter(); | |
493 NumberFormat wf = getWFormatter(); | |
494 NumberFormat qf = getQFormatter(); | |
495 | |
496 writer.writeNext(new String[] { | |
497 kmf.format(wqkm[2]), | |
498 wf.format(wqkm[0]), | |
499 qf.format(wqkm[1]), | |
500 wOrQDesc, | |
501 FLYSUtils.getLocationDescription(flys, wqkm[2]), | |
502 gaugeName | |
503 }); | |
504 } | |
505 | |
506 | |
507 /** | |
508 * Write "rows" of csv data from wqkms with writer. | |
509 */ | |
510 protected void wQKms2CSV( | |
511 CSVWriter writer, | |
512 WQKms wqkms, | |
513 boolean atGauge, | |
514 boolean isQ | |
515 ) { | |
516 logger.debug("WaterlevelExporter.wQKms2CSV"); | |
517 | |
518 // Skip constant data. | |
519 if (wqkms instanceof ConstantWQKms) { | |
520 return; | |
521 } | |
522 | |
523 NumberFormat kmf = getKmFormatter(); | |
524 NumberFormat wf = getWFormatter(); | |
525 NumberFormat qf = getQFormatter(); | |
526 | |
527 int size = wqkms.size(); | |
528 double[] result = new double[3]; | |
529 | |
530 FLYSArtifact flys = (FLYSArtifact) master; | |
531 List<Gauge> gauges = FLYSUtils.getGauges(flys); | |
532 Gauge gauge = FLYSUtils.getGauge(flys); | |
533 String gaugeName = gauge.getName(); | |
534 String desc = ""; | |
535 String notinrange = msg( | |
536 CSV_NOT_IN_GAUGE_RANGE, | |
537 DEFAULT_CSV_NOT_IN_GAUGE_RANGE); | |
538 | |
539 double a = gauge.getRange().getA().doubleValue(); | |
540 double b = gauge.getRange().getB().doubleValue(); | |
541 | |
542 if (flys instanceof WINFOArtifact && isQ) { | |
543 desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); | |
544 } | |
545 else if (!isQ) { | |
546 Double value = FLYSUtils.getValueFromWQ(wqkms); | |
547 desc = value != null | |
548 ? Formatter.getWaterlevelW(context).format(value) : null; | |
549 } | |
550 | |
551 long startTime = System.currentTimeMillis(); | |
552 | |
553 String colDesc = desc; | |
554 List<Segment> segments = null; | |
555 boolean isFixRealize = false; | |
556 if (flys instanceof WINFOArtifact) { | |
557 if (wqkms != null && wqkms.getRawValue() != null) { | |
558 WINFOArtifact winfo = (WINFOArtifact) flys; | |
559 colDesc = FLYSUtils.getNamedMainValue(winfo, wqkms.getRawValue()); | |
560 } | |
561 } | |
562 else if (flys instanceof FixationArtifact) { | |
563 // Get W/Q input per gauge for this case. | |
564 FixRealizingAccess fixAccess = new FixRealizingAccess(flys, getCallContext()); | |
565 segments = fixAccess.getSegments(); | |
566 if (segments != null && !segments.isEmpty()) { | |
567 isFixRealize = true; | |
568 } | |
569 } | |
570 | |
571 if (atGauge) { // "At gauge" needs more output. | |
572 | |
573 // Kms tend to be close together so caching the last sector | |
574 // is a good time saving heuristic. | |
575 Segment lastSegment = null; | |
576 Gauge lastGauge = null; | |
577 | |
578 NumberFormat nf = | |
579 Formatter.getFormatter(context.getMeta(), 0, 0); | |
580 | |
581 for (int i = 0; i < size; ++i) { | |
582 result = wqkms.get(i, result); | |
583 double km = result[2]; | |
584 | |
585 if (segments != null) { | |
586 Segment found = lastSegment != null | |
587 && lastSegment.inside(km) | |
588 ? lastSegment | |
589 : findSegment(km, segments); | |
590 | |
591 if (found != null) { | |
592 colDesc = nf.format(found.getValues()[0]); | |
593 } | |
594 lastSegment = found; | |
595 } | |
596 | |
597 String gaugeN; | |
598 if (isFixRealize) { | |
599 Gauge found = lastGauge != null | |
600 && lastGauge.getRange().contains(km) | |
601 ? lastGauge | |
602 : findGauge(km, gauges); | |
603 | |
604 gaugeN = found != null ? found.getName() : notinrange; | |
605 lastGauge = found; | |
606 } | |
607 else { | |
608 // TODO issue1114: Take correct gauge | |
609 gaugeN = km >= a && km <= b | |
610 ? gaugeName | |
611 : notinrange; | |
612 } | |
613 writeRow6(writer, result, colDesc, flys, gaugeN); | |
614 } | |
615 } | |
616 else { // Not at gauge. | |
617 for (int i = 0; i < size; ++i) { | |
618 result = wqkms.get(i, result); | |
619 writeRow4(writer, result, flys); | |
620 } | |
621 } | |
622 | |
623 long stopTime = System.currentTimeMillis(); | |
624 | |
625 if (logger.isDebugEnabled()) { | |
626 logger.debug("Writing CSV took " + | |
627 (float)(stopTime-startTime)/1000f + " secs."); | |
628 } | |
629 } | |
630 | |
631 | |
632 /** | |
633 * Generates the output in WST format. | |
634 */ | |
635 protected void generateWST() | |
636 throws IOException | |
637 { | |
638 logger.info("WaterlevelExporter.generateWST"); | |
639 | |
640 int cols = data.get(0).length; | |
641 WstWriter writer = new WstWriter(cols); | |
642 | |
643 writeWSTData(writer); | |
644 | |
645 writer.write(out); | |
646 } | |
647 | |
648 | |
649 protected void writeWSTData(WstWriter writer) { | |
650 logger.debug("WaterlevelExporter.writeWSTData"); | |
651 | |
652 double[] result = new double[4]; | |
653 | |
654 for (WQKms[] tmp: data) { | |
655 for (WQKms wqkms: tmp) { | |
656 if (wqkms instanceof ConstantWQKms) { | |
657 continue; | |
658 } | |
659 int size = wqkms != null ? wqkms.size() : 0; | |
660 | |
661 addWSTColumn(writer, wqkms); | |
662 | |
663 for (int i = 0; i < size; i++) { | |
664 result = wqkms.get(i, result); | |
665 | |
666 writer.add(result); | |
667 } | |
668 | |
669 if (wqkms instanceof WQCKms) { | |
670 addWSTColumn(writer, wqkms); | |
671 | |
672 for (int c = 0; c < size; c++) { | |
673 result = wqkms.get(c, result); | |
674 | |
675 writer.addCorrected(result); | |
676 } | |
677 } | |
678 } | |
679 } | |
680 } | |
681 | |
682 | |
683 /** | |
684 * This method is used to register a new column at <i>writer</i>. The name / | |
685 * title of the column depends on the Q or W value of <i>wqkms</i>. If a Q | |
686 * was selected and the Q fits to a named main value, the title is set to | |
687 * the named main value. Otherwise, the name returned by | |
688 * <i>WQKms.getName()</i> is set. | |
689 * | |
690 * @param writer The WstWriter. | |
691 * @param wqkms The new WST column. | |
692 */ | |
693 protected void addWSTColumn(WstWriter writer, WQKms wqkms) { | |
694 if (wqkms instanceof ConstantWQKms) { | |
695 return; | |
696 } | |
697 if (master instanceof WINFOArtifact) { | |
698 writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms)); | |
699 } | |
700 else { | |
701 writer.addColumn(wqkms.getName()); | |
702 } | |
703 } | |
704 | |
705 | |
706 /** | |
707 * | |
708 */ | |
709 @Override | |
710 protected void writePDF(OutputStream out) { | |
711 logger.debug("write PDF"); | |
712 WKmsJRDataSource source = createJRData(); | |
713 | |
714 String jasperFile = Resources.getMsg( | |
715 context.getMeta(), | |
716 JASPER_FILE, | |
717 "/jasper/waterlevel_en.jasper"); | |
718 String confPath = Config.getConfigDirectory().toString(); | |
719 | |
720 | |
721 Map parameters = new HashMap(); | |
722 parameters.put("ReportTitle", "Exported Data"); | |
723 try { | |
724 JasperPrint print = JasperFillManager.fillReport( | |
725 confPath + jasperFile, | |
726 parameters, | |
727 source); | |
728 JasperExportManager.exportReportToPdfStream(print, out); | |
729 } | |
730 catch(JRException je) { | |
731 logger.warn("Error generating PDF Report!", je); | |
732 } | |
733 } | |
734 | |
735 protected WKmsJRDataSource createJRData() { | |
736 WKmsJRDataSource source = new WKmsJRDataSource(); | |
737 | |
738 WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); | |
739 boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; | |
740 boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; | |
741 | |
742 addMetaData(source); | |
743 for (WQKms[] tmp: data) { | |
744 for (WQKms wqkms: tmp) { | |
745 addWKmsData(wqkms, atGauge, isQ, source); | |
746 } | |
747 } | |
748 return source; | |
749 } | |
750 | |
751 protected void addMetaData(WKmsJRDataSource source) { | |
752 CallMeta meta = context.getMeta(); | |
753 | |
754 FLYSArtifact flys = (FLYSArtifact) master; | |
755 | |
756 source.addMetaData ("river", FLYSUtils.getRivername(flys)); | |
757 | |
758 Locale locale = Resources.getLocale(meta); | |
759 DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); | |
760 | |
761 source.addMetaData("date", df.format(new Date())); | |
762 | |
763 RangeAccess rangeAccess = new RangeAccess(flys, null); | |
764 double[] kms = rangeAccess.getKmRange(); | |
765 source.addMetaData("range", kms[0] + " - " + kms[kms.length-1]); | |
766 | |
767 source.addMetaData("gauge", FLYSUtils.getGaugename(flys)); | |
768 | |
769 source.addMetaData("calculation", Resources.getMsg( | |
770 locale, | |
771 PDF_HEADER_MODE, | |
772 "Waterlevel")); | |
773 } | |
774 | |
775 protected void addWKmsData( | |
776 WQKms wqkms, | |
777 boolean atGauge, | |
778 boolean isQ, | |
779 WKmsJRDataSource source) | |
780 { | |
781 logger.debug("WaterlevelExporter.addWKmsData"); | |
782 | |
783 // Skip constant data. | |
784 if (wqkms instanceof ConstantWQKms) { | |
785 return; | |
786 } | |
787 | |
788 NumberFormat kmf = getKmFormatter(); | |
789 NumberFormat wf = getWFormatter(); | |
790 NumberFormat qf = getQFormatter(); | |
791 | |
792 int size = wqkms.size(); | |
793 double[] result = new double[3]; | |
794 | |
795 FLYSArtifact flys = (FLYSArtifact) master; | |
796 Gauge gauge = FLYSUtils.getGauge(flys); | |
797 String gaugeName = gauge.getName(); | |
798 String desc = ""; | |
799 String notinrange = msg( | |
800 CSV_NOT_IN_GAUGE_RANGE, | |
801 DEFAULT_CSV_NOT_IN_GAUGE_RANGE); | |
802 | |
803 double a = gauge.getRange().getA().doubleValue(); | |
804 double b = gauge.getRange().getB().doubleValue(); | |
805 | |
806 if (flys instanceof WINFOArtifact && isQ) { | |
807 desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); | |
808 } | |
809 else if (!isQ) { | |
810 Double value = FLYSUtils.getValueFromWQ(wqkms); | |
811 desc = value != null | |
812 ? Formatter.getWaterlevelW(context).format(value) : null; | |
813 } | |
814 | |
815 long startTime = System.currentTimeMillis(); | |
816 | |
817 for (int i = 0; i < size; i ++) { | |
818 result = wqkms.get(i, result); | |
819 | |
820 if (atGauge) { | |
821 source.addData(new String[] { | |
822 kmf.format(result[2]), | |
823 wf.format(result[0]), | |
824 qf.format(result[1]), | |
825 desc, | |
826 FLYSUtils.getLocationDescription(flys, result[2]), | |
827 result[2] >= a && result[2] <= b | |
828 ? gaugeName | |
829 : notinrange | |
830 }); | |
831 } | |
832 else { | |
833 source.addData(new String[] { | |
834 kmf.format(result[2]), | |
835 wf.format(result[0]), | |
836 qf.format(result[1]), | |
837 desc, | |
838 FLYSUtils.getLocationDescription(flys, result[2]), | |
839 result[2] >= a && result[2] <= b | |
840 ? gaugeName | |
841 : notinrange | |
842 }); | |
843 } | |
844 } | |
845 | |
846 long stopTime = System.currentTimeMillis(); | |
847 | |
848 if (logger.isDebugEnabled()) { | |
849 logger.debug("Writing PDF data took " + | |
850 (float)(stopTime-startTime)/1000f + " secs."); | |
851 } | |
852 } | |
853 } | |
854 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |