comparison flys-artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java@7b1c5fe4ebf3
children
comparison
equal deleted inserted replaced
5830:160f53ee0870 5831:bd047b71ab37
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 :

http://dive4elements.wald.intevation.org