diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/FixWaterlevelExporter.java	Tue Aug 28 14:02:23 2018 +0200
@@ -0,0 +1,259 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.exports;
+
+import java.io.OutputStream;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResults;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.JasperReporter;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.model.ConstantWQKms;
+import org.dive4elements.river.artifacts.model.DischargeTables;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.utils.Formatter;
+import org.dive4elements.river.utils.RiverUtils;
+import org.dive4elements.river.utils.RiverUtils.WQ_MODE;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import net.sf.jasperreports.engine.JRException;
+
+/**
+ * Generates different output formats (wst, csv, pdf) of data that resulted from
+ * a waterlevel computation.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FixWaterlevelExporter extends WaterlevelExporter {
+
+    /** The log used in this exporter. */
+    private static Logger log = Logger.getLogger(FixWaterlevelExporter.class);
+
+    private final Map<String, Double> gaugeQ_W_Map = new HashMap<>();
+
+    @Override
+    protected void writeRow4(final CSVWriter writer, final double wqkm[], final D4EArtifact flys, final Gauge gauge) {
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
+
+        final String waterlevel = getWaterlevel(wqkm[1], gauge);
+
+        writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])),
+                RiverUtils.getLocationDescription(flys, wqkm[2]) });
+    }
+
+    /** Write an csv-row at gauge location. */
+    @Override
+    protected void writeRow6(final CSVWriter writer, final double wqkm[], final String wOrQDesc, final D4EArtifact flys, final Gauge gauge) {
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
+
+        final String waterlevel = getWaterlevel(wqkm[1], gauge);
+
+        writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc,
+                RiverUtils.getLocationDescription(flys, wqkm[2]), gauge.getName() });
+    }
+
+    private String getWaterlevel(final double discharge, final Gauge gauge) {
+        final NumberFormat formatter = Formatter.getWaterlevelW(this.context);
+        final Double waterlevel = this.getWforGaugeAndQ(gauge, discharge);
+        return formatter.format(waterlevel);
+    }
+
+    private Double getWforGaugeAndQ(final Gauge gauge, final double q) {
+
+        final String key = gauge.getName() + String.valueOf(q);
+        if (!this.gaugeQ_W_Map.containsKey(key)) {
+
+            final DischargeTables dct = new DischargeTables(gauge.getRiver().getName(), gauge.getName());
+            final double[] qs = DischargeTables.getWsForQ(dct.getFirstTable(), q); // TODO: KLÄREN, welche Abflusstabelle genommen werden soll!
+            if (qs != null && qs.length > 0) {
+                this.gaugeQ_W_Map.put(key, qs[0]);
+            }
+        }
+        return this.gaugeQ_W_Map.get(key);
+    }
+
+    /**
+     * Write the header, with different headings depending on whether at a
+     * gauge or at a location.
+     */
+
+    @Override
+    protected void writeCSVHeader(final CSVWriter writer, final boolean atGauge, final boolean isQ) {
+        log.info("WaterlevelExporter.writeCSVHeader");
+
+        final String unit = RiverUtils.getRiver((D4EArtifact) this.master).getWstUnit().getName();
+
+        final String headerWamPegelNeu = msg("fix.export.csv.w_at_gauge");
+
+        if (atGauge) {
+            writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
+                    headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
+
+                    // FIXME: use WaterlevelDescriptionBuilder instead and also remove all this duplicate code.
+                    (isQ ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)),
+                    msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) });
+        } else {
+            writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
+                    headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) });
+        }
+    }
+
+    @Override
+    protected void writePDF(final OutputStream out) {
+
+        log.debug("write PDF");
+
+        final MetaAndTableJRDataSource source = new MetaAndTableJRDataSource();
+        final String jasperFile = "/jasper/templates/fix_waterlevel.jrxml"; // "/jasper/fix_waterlevel_en.jasper");
+
+        addMetaData(source);
+        try {
+            final List<String[]> sorted = getRows(); // Custom Result could be nice, too...
+            for (final String[] list : sorted) {
+                source.addData(list);
+            }
+
+            final JasperReporter reporter = new JasperReporter();
+            reporter.addReport(jasperFile, source);
+            reporter.exportPDF(out);
+        }
+        catch (final JRException je) {
+            log.warn("Error generating PDF Report!", je);
+        }
+    }
+
+    private void addMetaData(final MetaAndTableJRDataSource source) {
+        final D4EArtifact flys = (D4EArtifact) this.master;
+        final String user = CalculationUtils.findArtifactUser(this.context, flys);
+        final RangeAccess ra = new RangeAccess(flys);
+        final RiverInfo ri = new RiverInfo(ra.getRiver());
+
+        final DefaultCalculationResults results = new DefaultCalculationResults(msg("calculation.analysis"), user, ri, ra.getRange());
+        final ExportContextPDF contextPdf = new ExportContextPDF(this.context, results);
+        contextPdf.addJRMetaDataDefaults(source);
+        contextPdf.addJRMetaDataForModules(source);
+
+        /* column headings */
+        contextPdf.addJRMetadata(source, "station_header", GeneralResultType.station);
+        contextPdf.addJRMetadata(source, "fix_w", msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { ri.getWstUnit() }));
+        contextPdf.addJRMetadata(source, "w_at_gauge_header", msg("fix.export.csv.w_at_gauge"));
+        contextPdf.addJRMetadata(source, "fix_q", msg(CSV_Q_HEADER));
+        contextPdf.addJRMetadata(source, "waterlevel_name_header", msg("common.export.csv.header.mainvalue_label"));
+        contextPdf.addJRMetadata(source, "location_header", msg("common.export.csv.header.location"));
+        contextPdf.addJRMetadata(source, "gauge_header", msg("common.export.csv.header.gauge"));
+
+    }
+
+    private List<String[]> getRows() {
+        final List<String[]> list = new ArrayList<>();
+        final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
+        final boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
+        final boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
+
+        Double first = Double.NaN;
+        Double last = Double.NaN;
+
+        for (final WQKms[] tmp : this.data) {
+            for (final WQKms wqkms : tmp) {
+                list.addAll(getRows2(wqkms, atGauge, isQ));
+                final double[] firstLast = wqkms.getFirstLastKM();
+                if (first.isNaN()) {
+                    /* Initialize */
+                    first = firstLast[0];
+                    last = firstLast[1];
+                }
+                if (firstLast[0] > firstLast[1]) {
+                    /*
+                     * Calculating upstream we assert that it is
+                     * impossible that the direction changes during this
+                     * loop
+                     */
+                    first = Math.max(first, firstLast[0]);
+                    last = Math.min(last, firstLast[1]);
+                } else if (firstLast[0] < firstLast[1]) {
+                    first = Math.min(first, firstLast[0]);
+                    last = Math.max(last, firstLast[1]);
+                } else {
+                    first = last = firstLast[0];
+                }
+            }
+        }
+
+        /* Append the official fixing at the bottom */
+        for (final WQKms wqkms : this.officalFixings) {
+            list.addAll(getRows2(filterWQKms(wqkms, first, last), atGauge, isQ));
+        }
+        return list;
+    }
+
+    protected List<String[]> getRows2(final WQKms wqkms, final boolean atGauge, final boolean isQ) {
+        log.debug("WaterlevelExporter.addWKmsData"); // OLD CODE :-/
+
+        final List<String[]> list = new ArrayList<>();
+        // Skip constant data.
+        if (wqkms instanceof ConstantWQKms) {
+            return null;
+        }
+
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
+
+        final int size = wqkms.size();
+        double[] result = new double[3];
+
+        final D4EArtifact flys = (D4EArtifact) this.master;
+        final RangeAccess rangeAccess = new RangeAccess(flys);
+
+        final Gauge gauge = rangeAccess.getRiver().determineRefGauge(rangeAccess.getKmRange(), rangeAccess.isRange());
+
+        final String gaugeName = gauge.getName();
+        String desc = "";
+        final String notinrange = msg(CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
+
+        final double a = gauge.getRange().getA().doubleValue();
+        final double b = gauge.getRange().getB().doubleValue();
+
+        desc = getDesc(wqkms, isQ);
+        final long startTime = System.currentTimeMillis();
+
+        for (int i = 0; i < size; i++) {
+            result = wqkms.get(i, result);
+            final double q = result[1];
+            final String waterlevel = this.getWaterlevel(q, gauge); // THIS IS NEW (and makes common super method
+                                                                    // difficult)
+            if (atGauge) {
+                list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc,
+                        RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
+            } else {
+                list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc,
+                        RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
+            }
+
+        }
+
+        return list;
+    }
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org