comparison artifacts/src/main/java/org/dive4elements/river/exports/FixWaterlevelExporter.java @ 9457:65f28328c9a3

ausgelagerte Wasserspiegellage AWSPL neue Spalte
author gernotbelger
date Tue, 28 Aug 2018 14:02:23 +0200
parents
children f06e3766997f
comparison
equal deleted inserted replaced
9456:c96f6c8a6b03 9457:65f28328c9a3
1 /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
2 * Software engineering by Intevation GmbH
3 *
4 * This file is Free Software under the GNU AGPL (>=v3)
5 * and comes with ABSOLUTELY NO WARRANTY! Check out the
6 * documentation coming with Dive4Elements River for details.
7 */
8
9 package org.dive4elements.river.exports;
10
11 import java.io.OutputStream;
12 import java.text.NumberFormat;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17
18 import org.apache.log4j.Logger;
19 import org.dive4elements.river.artifacts.D4EArtifact;
20 import org.dive4elements.river.artifacts.access.RangeAccess;
21 import org.dive4elements.river.artifacts.common.DefaultCalculationResults;
22 import org.dive4elements.river.artifacts.common.ExportContextPDF;
23 import org.dive4elements.river.artifacts.common.GeneralResultType;
24 import org.dive4elements.river.artifacts.common.JasperReporter;
25 import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
26 import org.dive4elements.river.artifacts.model.ConstantWQKms;
27 import org.dive4elements.river.artifacts.model.DischargeTables;
28 import org.dive4elements.river.artifacts.model.WQKms;
29 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
30 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
31 import org.dive4elements.river.model.Gauge;
32 import org.dive4elements.river.utils.Formatter;
33 import org.dive4elements.river.utils.RiverUtils;
34 import org.dive4elements.river.utils.RiverUtils.WQ_MODE;
35
36 import au.com.bytecode.opencsv.CSVWriter;
37 import net.sf.jasperreports.engine.JRException;
38
39 /**
40 * Generates different output formats (wst, csv, pdf) of data that resulted from
41 * a waterlevel computation.
42 *
43 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
44 */
45 public class FixWaterlevelExporter extends WaterlevelExporter {
46
47 /** The log used in this exporter. */
48 private static Logger log = Logger.getLogger(FixWaterlevelExporter.class);
49
50 private final Map<String, Double> gaugeQ_W_Map = new HashMap<>();
51
52 @Override
53 protected void writeRow4(final CSVWriter writer, final double wqkm[], final D4EArtifact flys, final Gauge gauge) {
54 final NumberFormat kmf = getKmFormatter();
55 final NumberFormat wf = getWFormatter();
56 final NumberFormat qf = getQFormatter();
57
58 final String waterlevel = getWaterlevel(wqkm[1], gauge);
59
60 writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])),
61 RiverUtils.getLocationDescription(flys, wqkm[2]) });
62 }
63
64 /** Write an csv-row at gauge location. */
65 @Override
66 protected void writeRow6(final CSVWriter writer, final double wqkm[], final String wOrQDesc, final D4EArtifact flys, final Gauge gauge) {
67 final NumberFormat kmf = getKmFormatter();
68 final NumberFormat wf = getWFormatter();
69 final NumberFormat qf = getQFormatter();
70
71 final String waterlevel = getWaterlevel(wqkm[1], gauge);
72
73 writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc,
74 RiverUtils.getLocationDescription(flys, wqkm[2]), gauge.getName() });
75 }
76
77 private String getWaterlevel(final double discharge, final Gauge gauge) {
78 final NumberFormat formatter = Formatter.getWaterlevelW(this.context);
79 final Double waterlevel = this.getWforGaugeAndQ(gauge, discharge);
80 return formatter.format(waterlevel);
81 }
82
83 private Double getWforGaugeAndQ(final Gauge gauge, final double q) {
84
85 final String key = gauge.getName() + String.valueOf(q);
86 if (!this.gaugeQ_W_Map.containsKey(key)) {
87
88 final DischargeTables dct = new DischargeTables(gauge.getRiver().getName(), gauge.getName());
89 final double[] qs = DischargeTables.getWsForQ(dct.getFirstTable(), q); // TODO: KLÄREN, welche Abflusstabelle genommen werden soll!
90 if (qs != null && qs.length > 0) {
91 this.gaugeQ_W_Map.put(key, qs[0]);
92 }
93 }
94 return this.gaugeQ_W_Map.get(key);
95 }
96
97 /**
98 * Write the header, with different headings depending on whether at a
99 * gauge or at a location.
100 */
101
102 @Override
103 protected void writeCSVHeader(final CSVWriter writer, final boolean atGauge, final boolean isQ) {
104 log.info("WaterlevelExporter.writeCSVHeader");
105
106 final String unit = RiverUtils.getRiver((D4EArtifact) this.master).getWstUnit().getName();
107
108 final String headerWamPegelNeu = msg("fix.export.csv.w_at_gauge");
109
110 if (atGauge) {
111 writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
112 headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
113
114 // FIXME: use WaterlevelDescriptionBuilder instead and also remove all this duplicate code.
115 (isQ ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)),
116 msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) });
117 } else {
118 writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
119 headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) });
120 }
121 }
122
123 @Override
124 protected void writePDF(final OutputStream out) {
125
126 log.debug("write PDF");
127
128 final MetaAndTableJRDataSource source = new MetaAndTableJRDataSource();
129 final String jasperFile = "/jasper/templates/fix_waterlevel.jrxml"; // "/jasper/fix_waterlevel_en.jasper");
130
131 addMetaData(source);
132 try {
133 final List<String[]> sorted = getRows(); // Custom Result could be nice, too...
134 for (final String[] list : sorted) {
135 source.addData(list);
136 }
137
138 final JasperReporter reporter = new JasperReporter();
139 reporter.addReport(jasperFile, source);
140 reporter.exportPDF(out);
141 }
142 catch (final JRException je) {
143 log.warn("Error generating PDF Report!", je);
144 }
145 }
146
147 private void addMetaData(final MetaAndTableJRDataSource source) {
148 final D4EArtifact flys = (D4EArtifact) this.master;
149 final String user = CalculationUtils.findArtifactUser(this.context, flys);
150 final RangeAccess ra = new RangeAccess(flys);
151 final RiverInfo ri = new RiverInfo(ra.getRiver());
152
153 final DefaultCalculationResults results = new DefaultCalculationResults(msg("calculation.analysis"), user, ri, ra.getRange());
154 final ExportContextPDF contextPdf = new ExportContextPDF(this.context, results);
155 contextPdf.addJRMetaDataDefaults(source);
156 contextPdf.addJRMetaDataForModules(source);
157
158 /* column headings */
159 contextPdf.addJRMetadata(source, "station_header", GeneralResultType.station);
160 contextPdf.addJRMetadata(source, "fix_w", msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { ri.getWstUnit() }));
161 contextPdf.addJRMetadata(source, "w_at_gauge_header", msg("fix.export.csv.w_at_gauge"));
162 contextPdf.addJRMetadata(source, "fix_q", msg(CSV_Q_HEADER));
163 contextPdf.addJRMetadata(source, "waterlevel_name_header", msg("common.export.csv.header.mainvalue_label"));
164 contextPdf.addJRMetadata(source, "location_header", msg("common.export.csv.header.location"));
165 contextPdf.addJRMetadata(source, "gauge_header", msg("common.export.csv.header.gauge"));
166
167 }
168
169 private List<String[]> getRows() {
170 final List<String[]> list = new ArrayList<>();
171 final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
172 final boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
173 final boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
174
175 Double first = Double.NaN;
176 Double last = Double.NaN;
177
178 for (final WQKms[] tmp : this.data) {
179 for (final WQKms wqkms : tmp) {
180 list.addAll(getRows2(wqkms, atGauge, isQ));
181 final double[] firstLast = wqkms.getFirstLastKM();
182 if (first.isNaN()) {
183 /* Initialize */
184 first = firstLast[0];
185 last = firstLast[1];
186 }
187 if (firstLast[0] > firstLast[1]) {
188 /*
189 * Calculating upstream we assert that it is
190 * impossible that the direction changes during this
191 * loop
192 */
193 first = Math.max(first, firstLast[0]);
194 last = Math.min(last, firstLast[1]);
195 } else if (firstLast[0] < firstLast[1]) {
196 first = Math.min(first, firstLast[0]);
197 last = Math.max(last, firstLast[1]);
198 } else {
199 first = last = firstLast[0];
200 }
201 }
202 }
203
204 /* Append the official fixing at the bottom */
205 for (final WQKms wqkms : this.officalFixings) {
206 list.addAll(getRows2(filterWQKms(wqkms, first, last), atGauge, isQ));
207 }
208 return list;
209 }
210
211 protected List<String[]> getRows2(final WQKms wqkms, final boolean atGauge, final boolean isQ) {
212 log.debug("WaterlevelExporter.addWKmsData"); // OLD CODE :-/
213
214 final List<String[]> list = new ArrayList<>();
215 // Skip constant data.
216 if (wqkms instanceof ConstantWQKms) {
217 return null;
218 }
219
220 final NumberFormat kmf = getKmFormatter();
221 final NumberFormat wf = getWFormatter();
222 final NumberFormat qf = getQFormatter();
223
224 final int size = wqkms.size();
225 double[] result = new double[3];
226
227 final D4EArtifact flys = (D4EArtifact) this.master;
228 final RangeAccess rangeAccess = new RangeAccess(flys);
229
230 final Gauge gauge = rangeAccess.getRiver().determineRefGauge(rangeAccess.getKmRange(), rangeAccess.isRange());
231
232 final String gaugeName = gauge.getName();
233 String desc = "";
234 final String notinrange = msg(CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
235
236 final double a = gauge.getRange().getA().doubleValue();
237 final double b = gauge.getRange().getB().doubleValue();
238
239 desc = getDesc(wqkms, isQ);
240 final long startTime = System.currentTimeMillis();
241
242 for (int i = 0; i < size; i++) {
243 result = wqkms.get(i, result);
244 final double q = result[1];
245 final String waterlevel = this.getWaterlevel(q, gauge); // THIS IS NEW (and makes common super method
246 // difficult)
247 if (atGauge) {
248 list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc,
249 RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
250 } else {
251 list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc,
252 RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
253 }
254
255 }
256
257 return list;
258 }
259 }

http://dive4elements.wald.intevation.org