changeset 9457:65f28328c9a3

ausgelagerte Wasserspiegellage AWSPL neue Spalte
author gernotbelger
date Tue, 28 Aug 2018 14:02:23 +0200
parents c96f6c8a6b03
children 7369d6ae3f87
files artifacts/doc/conf/artifacts/bundu.xml artifacts/doc/conf/generators/generators.xml artifacts/doc/conf/jasper/templates/fix_waterlevel.jrxml artifacts/src/main/java/org/dive4elements/river/exports/FixWaterlevelExporter.java artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java artifacts/src/main/resources/messages.properties artifacts/src/main/resources/messages_de.properties
diffstat 7 files changed, 588 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/bundu.xml	Tue Aug 28 13:50:05 2018 +0200
+++ b/artifacts/doc/conf/artifacts/bundu.xml	Tue Aug 28 14:02:23 2018 +0200
@@ -545,7 +545,7 @@
             <facet name="longitudinal_section.manualpoints" description="Manuelle Punkte"/>
           </facets>
         </outputmode>
-        <outputmode name="bundu_wst_export" description="output.fix_waterlevel_export" mine-type="text/plain" type="export">
+        <outputmode name="bundu_wst_export" description="output.TODO_MAKE_DESCRIPTION_FOR_WST_EXPORT" mine-type="text/plain" type="export">
           <facets>
             <facet name="csv" description="facet.waterlevel_export.csv"/>
             <facet name="pdf" description="facet.waterlevel_export.pdf"/>
--- a/artifacts/doc/conf/generators/generators.xml	Tue Aug 28 13:50:05 2018 +0200
+++ b/artifacts/doc/conf/generators/generators.xml	Tue Aug 28 14:02:23 2018 +0200
@@ -39,7 +39,7 @@
   <output-generator names="fix_deltawt_export" class="org.dive4elements.river.exports.fixings.DeltaWtExporter" />
   <output-generator names="fix_deltawt_curve" class="org.dive4elements.river.exports.fixings.FixDeltaWtGenerator" />
   <output-generator names="fix_deltawt_curve_chartinfo" class="org.dive4elements.river.exports.fixings.FixDeltaWtInfoGenerator" />
-  <output-generator names="fix_waterlevel_export" class="org.dive4elements.river.exports.WaterlevelExporter" />
+  <output-generator names="fix_waterlevel_export" class="org.dive4elements.river.exports.FixWaterlevelExporter" />
   <output-generator names="bundu_wst_export" class="org.dive4elements.river.artifacts.bundu.bezugswst.BunduWstExporter" />
   <output-generator names="sedimentload_ls_export" class="org.dive4elements.river.exports.minfo.SedimentLoadExporter" />
   <!-- Error report generators. -->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/fix_waterlevel.jrxml	Tue Aug 28 14:02:23 2018 +0200
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.6.0.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-08-28T11:58:49 -->
+<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="flysreport" language="groovy" pageWidth="595" pageHeight="842" columnWidth="545" leftMargin="30" rightMargin="20" topMargin="20" bottomMargin="20">
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:w_at_gauge_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:fix_date" class="java.lang.String"/>
+	<field name="meta:fix_q" class="java.lang.String"/>
+	<field name="meta:fix_w" class="java.lang.String"/>
+	<field name="meta:fix_state" class="java.lang.String"/>
+	<field name="meta:fix_delta_w" class="java.lang.String"/>
+	<field name="data:0" class="java.lang.String"/>
+	<field name="data:1" class="java.lang.String"/>
+	<field name="data:2" class="java.lang.String"/>
+	<field name="data:3" class="java.lang.String"/>
+	<field name="data:4" class="java.lang.String"/>
+	<field name="data:5" class="java.lang.String"/>
+	<field name="data:6" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="550" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="85" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:fix_w}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="145" y="0" width="63" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:w_at_gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="208" y="0" width="70" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:fix_q}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="278" y="0" width="85" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="363" y="0" width="85" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="448" y="0" width="102" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="145" y="0" width="63" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="208" y="0" width="70" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="278" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="363" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="448" y="0" width="102" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="437" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="493" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+</jasperReport>
--- /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
--- a/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java	Tue Aug 28 13:50:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java	Tue Aug 28 14:02:23 2018 +0200
@@ -64,10 +64,10 @@
     /** The log used in this exporter. */
     private static Logger log = Logger.getLogger(WaterlevelExporter.class);
 
-    public static final String FACET_WST = "wst";
+    private static final String FACET_WST = "wst";
 
     /* This should be the same as in the StaticWQKmsArtifact */
-    public static final String STATICWQKMSNAME = "staticwqkms";
+    private static final String STATICWQKMSNAME = "staticwqkms";
 
     public static final String CSV_KM_HEADER = "export.waterlevel.csv.header.km";
 
@@ -91,25 +91,25 @@
 
     public static final String CSV_GAUGE_HEADER = "export.waterlevel.csv.header.gauge";
 
-    public static final String CSV_META_RESULT = "export.waterlevel.csv.meta.result";
-
-    public static final String CSV_META_CREATION = "export.waterlevel.csv.meta.creation";
-
-    public static final String CSV_META_CALCULATIONBASE = "export.waterlevel.csv.meta.calculationbase";
+    private static final String CSV_META_RESULT = "export.waterlevel.csv.meta.result";
 
-    public static final String CSV_META_RIVER = "export.waterlevel.csv.meta.river";
-
-    public static final String CSV_META_RANGE = "export.waterlevel.csv.meta.range";
+    private static final String CSV_META_CREATION = "export.waterlevel.csv.meta.creation";
 
-    public static final String CSV_META_GAUGE = "export.waterlevel.csv.meta.gauge";
+    private static final String CSV_META_CALCULATIONBASE = "export.waterlevel.csv.meta.calculationbase";
 
-    public static final String CSV_META_Q = "common.export.waterlevel.csv.meta.q";
+    private static final String CSV_META_RIVER = "export.waterlevel.csv.meta.river";
 
-    public static final String CSV_META_W = "export.waterlevel.csv.meta.w";
+    private static final String CSV_META_RANGE = "export.waterlevel.csv.meta.range";
+
+    private static final String CSV_META_GAUGE = "export.waterlevel.csv.meta.gauge";
+
+    private static final String CSV_META_Q = "common.export.waterlevel.csv.meta.q";
+
+    private static final String CSV_META_W = "export.waterlevel.csv.meta.w";
 
     public static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range";
 
-    public static final Pattern NUMBERS_PATTERN = Pattern.compile("\\D*(\\d++.\\d*)\\D*");
+    private static final Pattern NUMBERS_PATTERN = Pattern.compile("\\D*(\\d++.\\d*)\\D*");
 
     public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km";
     public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]";
@@ -128,14 +128,14 @@
     public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel";
     public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = "außerhalb des gewählten Bezugspegels";
 
-    public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode";
-    public static final String JASPER_FILE = "export.waterlevel.pdf.file";
+    protected static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode";
+    private static final String JASPER_FILE = "export.waterlevel.pdf.file";
 
     /** The storage that contains all WQKms objects that are calculated. */
-    protected List<WQKms[]> data;
+    public List<WQKms[]> data;
 
     /** The storage that contains official fixings if available. */
-    protected List<WQKms> officalFixings;
+    public List<WQKms> officalFixings;
 
     public WaterlevelExporter() {
         this.data = new ArrayList<>();
@@ -216,7 +216,7 @@
      * @param wqkms
      *            A WQKms object that should be prepared.
      */
-    protected String getColumnTitle(final WINFOArtifact winfo, final WQKms wqkms) {
+    public String getColumnTitle(final WINFOArtifact winfo, final WQKms wqkms) {
         log.debug("WaterlevelExporter.getColumnTitle");
 
         final String name = wqkms.getName();
@@ -257,7 +257,7 @@
      * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
      */
     @Deprecated
-    protected String getCSVRowTitle(final WINFOArtifact winfo, final WQKms wqkms) {
+    public String getCSVRowTitle(final WINFOArtifact winfo, final WQKms wqkms) {
         log.debug("WaterlevelExporter.prepareNamedValue");
 
         final String name = wqkms.getName();
@@ -291,7 +291,7 @@
      * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
      */
     @Deprecated
-    protected String localizeWQKms(final WINFOArtifact winfo, final WQKms wqkms) {
+    public String localizeWQKms(final WINFOArtifact winfo, final WQKms wqkms) {
         final WQ_MODE wqmode = RiverUtils.getWQMode(winfo);
         final Double rawValue = wqkms.getRawValue();
 
@@ -309,7 +309,7 @@
     }
 
     @Override
-    protected void writeCSVData(final CSVWriter writer) {
+    public void writeCSVData(final CSVWriter writer) {
         log.info("WaterlevelExporter.writeData");
 
         final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
@@ -371,7 +371,7 @@
      *
      * @return A new WQKms with the relevant data sorted by direction
      */
-    private WQKms filterWQKms(final WQKms wqkms, final Double first, final Double last) {
+    public final WQKms filterWQKms(final WQKms wqkms, final Double first, final Double last) {
         if (first.isNaN() || last.isNaN()) {
             log.warn("Filtering official fixing without valid first/last.");
             return wqkms;
@@ -400,7 +400,7 @@
         return filtered;
     }
 
-    protected void writeCSVMeta(final CSVWriter writer) {
+    public void writeCSVMeta(final CSVWriter writer) {
         log.info("WaterlevelExporter.writeCSVMeta");
 
         // TODO use Access instead of RiverUtils
@@ -511,7 +511,7 @@
         return null;
     }
 
-    private void writeRow4(final CSVWriter writer, final double wqkm[], final D4EArtifact flys) {
+    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();
@@ -520,20 +520,20 @@
     }
 
     /** Write an csv-row at gauge location. */
-    private void writeRow6(final CSVWriter writer, final double wqkm[], final String wOrQDesc, final D4EArtifact flys, final String gaugeName) {
+    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();
 
         writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc,
-                RiverUtils.getLocationDescription(flys, wqkm[2]), gaugeName });
+                RiverUtils.getLocationDescription(flys, wqkm[2]), gauge.getName() });
     }
 
     /**
      * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
      */
     @Deprecated
-    private String getDesc(final WQKms wqkms, final boolean isQ) {
+    public final String getDesc(final WQKms wqkms, final boolean isQ) {
         final D4EArtifact flys = (D4EArtifact) this.master;
         String colDesc = "";
 
@@ -644,12 +644,12 @@
                     // TODO issue1114: Take correct gauge
                     gaugeN = km >= a && km <= b ? gaugeName : notinrange;
                 }
-                writeRow6(writer, result, desc, flys, gaugeN);
+                writeRow6(writer, result, desc, flys, gauge);
             }
         } else { // Not at gauge.
             for (int i = 0; i < size; ++i) {
                 result = wqkms.get(i, result);
-                writeRow4(writer, result, flys);
+                writeRow4(writer, result, flys, gauge);
             }
         }
 
@@ -663,7 +663,7 @@
     /**
      * Generates the output in WST format.
      */
-    protected void generateWST() throws IOException {
+    public void generateWST() throws IOException {
         log.info("WaterlevelExporter.generateWST");
 
         final int cols = this.data.get(0).length + this.officalFixings.size();
@@ -674,7 +674,7 @@
         writer.write(this.out);
     }
 
-    protected void writeWSTData(final WstWriter writer) {
+    public void writeWSTData(final WstWriter writer) {
         log.debug("WaterlevelExporter.writeWSTData");
 
         double[] result = new double[4];
@@ -755,27 +755,31 @@
         }
     }
 
-    @Override
-    protected void writePDF(final OutputStream out) {
-        log.debug("write PDF");
-        final WKmsJRDataSource source = createJRData();
+    public void doWritePdf(final WKmsJRDataSource source, final String jasperFile) {
 
-        final String jasperFile = // "/jasper/waterlevel_en.jasper";
-                Resources.getMsg(this.context.getMeta(), JASPER_FILE, "/jasper/waterlevel_en.jasper");
         final String confPath = Config.getConfigDirectory().toString();
 
         final Map parameters = new HashMap();
         parameters.put("ReportTitle", "Exported Data");
         try {
             final JasperPrint print = JasperFillManager.fillReport(confPath + jasperFile, parameters, source);
-            JasperExportManager.exportReportToPdfStream(print, out);
+            JasperExportManager.exportReportToPdfStream(print, this.out);
         }
         catch (final JRException je) {
             log.warn("Error generating PDF Report!", je);
         }
     }
 
-    protected WKmsJRDataSource createJRData() {
+    @Override
+    protected void writePDF(final OutputStream out) {
+        log.debug("write PDF");
+        final WKmsJRDataSource source = createJRData();
+        final String jasperFile = Resources.getMsg(this.context.getMeta(), JASPER_FILE, "/jasper/waterlevel_en.jasper");
+        doWritePdf(source, jasperFile);
+
+    }
+
+    private WKmsJRDataSource createJRData() {
         final WKmsJRDataSource source = new WKmsJRDataSource();
 
         final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
@@ -819,7 +823,7 @@
         return source;
     }
 
-    protected void addMetaData(final WKmsJRDataSource source) {
+    public void addMetaData(final WKmsJRDataSource source) {
         final CallMeta meta = this.context.getMeta();
 
         final D4EArtifact flys = (D4EArtifact) this.master;
@@ -836,6 +840,10 @@
         final double[] kms = rangeAccess.getKmRange();
         source.addMetaData("range", kmf.format(kms[0]) + " - " + kmf.format(kms[kms.length - 1]));
 
+        source.addMetaData("w_at_gauge_header", Resources.getMsg(meta, "fix.export.csv.w_at_gauge")); // dürfte kein Problem sein für Vorlagen, die kein
+                                                                                                      // "w_at_gauge"
+        // haben
+
         source.addMetaData("gauge", RiverUtils.getGaugename(flys));
 
         source.addMetaData("calculation", Resources.getMsg(locale, PDF_HEADER_MODE, "Waterlevel"));
@@ -881,6 +889,7 @@
                 source.addData(new String[] { kmf.format(result[2]), wf.format(result[0]), qf.format(RiverUtils.roundQ(result[1])), desc,
                         RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
             }
+
         }
 
         final long stopTime = System.currentTimeMillis();
@@ -889,5 +898,6 @@
             log.debug("Writing PDF data took " + (stopTime - startTime) / 1000f + " secs.");
         }
     }
+
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/resources/messages.properties	Tue Aug 28 13:50:05 2018 +0200
+++ b/artifacts/src/main/resources/messages.properties	Tue Aug 28 14:02:23 2018 +0200
@@ -677,6 +677,7 @@
 fix.mq=arraound MQ
 fix.mhq=arround MHQ
 fix.hq5=over HQ5
+fix.export.csv.w_at_gauge = W at Gauge [cm]
 
 chart.fix.deltawt.title=Difference from compensating curve at kilometer {0}
 chart.fix.deltawt.subtitle=Water: {0}; Period:  {1,date,short} to {2,date,short}; Reference period: {3,date,short} bis {4,date,short}
@@ -943,12 +944,12 @@
 sinfo.export.flow_depth.pdf.header.waterlevel = Wasser-stand
 sinfo.export.flow_depth.csv.header.discharge = Q
 sinfo.export.collision.csv.header.discharge_long = Abfluss
-common.export.csv.header.mainvalue_label = Bezeichnung
-common.export.csv.header.gauge = Bezugspegel
+common.export.csv.header.mainvalue_label = Description
+common.export.csv.header.gauge = Reference Gauge
 sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he
 sinfo.export.flow_depth.csv.header.mean_bed_height.short = Mittlere Sohl-
 sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
-common.export.csv.header.location = Lage
+common.export.csv.header.location = Location
 
 sinfo.export.flood_duration.csv.header.riverside = Uferseite
 sinfo.export.flood_duration.csv.header.infrastructure.height = H\u00f6he der Infrastruktur
--- a/artifacts/src/main/resources/messages_de.properties	Tue Aug 28 13:50:05 2018 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Tue Aug 28 14:02:23 2018 +0200
@@ -677,6 +677,7 @@
 fix.mq=um MQ
 fix.mhq=um MHQ
 fix.hq5=um HQ5
+fix.export.csv.w_at_gauge = W am Pegel [cm]
 
 chart.fix.deltawt.title=Abweichungen von der Ausgleichskurve an Kilometer {0}
 chart.fix.deltawt.subtitle=Gew\u00e4sser: {0}; Darstellungszeitraum: {1,date,short} bis {2,date,short}; Bezugszeitraum: {3,date,short} bis {4,date,short}

http://dive4elements.wald.intevation.org