changeset 8854:7bbfb24e6eec

SINFO - first prototype of BArt Fließtiefen
author gernotbelger
date Thu, 18 Jan 2018 18:34:41 +0100
parents 8c64617a7991
children 28df64078f27
files artifacts/doc/conf/artifacts/sinfo.xml artifacts/doc/conf/conf.xml artifacts/doc/conf/generators/generators.xml artifacts/doc/conf/generators/longitudinal-diagram-defaults.xml artifacts/doc/conf/generators/longitudinal-diagrams.xml artifacts/doc/conf/jasper/FIXME.txt artifacts/doc/conf/jasper/templates/sinfo.flowdepth.jrxml artifacts/doc/conf/meta-data.xml artifacts/doc/conf/modules.xml artifacts/doc/conf/themes.xml artifacts/doc/conf/themes/default.xml artifacts/doc/conf/themes/second.xml artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/CalculationSelectSinfo.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/SINFOArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/SinfoCalcMode.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthAccess.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculationResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculationResults.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthExporter.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthFilterFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthPairSelectState.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthProcessor.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthRow.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthState.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/UseTransportBodiesChoice.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/util/MetaAndTableJRDataSource.java artifacts/src/main/resources/messages.properties artifacts/src/main/resources/messages_de.properties artifacts/src/main/resources/messages_de_DE.properties artifacts/src/main/resources/messages_en.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/FlowDepthTwinPanel.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/FlowDepthTwinPanelValidator.java gwt-client/src/main/java/org/dive4elements/river/client/server/FLYSArtifactCreator.java gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SINFOArtifact.java gwt-client/src/main/webapp/WEB-INF/features.xml
diffstat 42 files changed, 2367 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/artifacts/sinfo.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<artifact name="sinfo">
+
+    <states>
+        <state id="state.sinfo.river" description="state.sinfo.river" state="org.dive4elements.river.artifacts.states.RiverSelect" helpText="help.state.sinfo.river">
+            <data name="river" type="String" />
+        </state>
+ 
+        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+                <from state="state.sinfo.river"/>
+                <to state="state.sinfo.calculation_mode"/>
+        </transition>
+
+        <state id="state.sinfo.calculation_mode" description="state.sinfo.calculation_mode" state="org.dive4elements.river.artifacts.sinfo.CalculationSelectSinfo" helpText="help.state.sinfo.calculation_mode">
+            <data name="calculation_mode" type="String"/>
+        </state>
+
+        <!-- Fliesstiefen -->
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.sinfo.calculation_mode"/>
+            <to state="state.sinfo.distance_only"/>
+            <condition data="calculation_mode" value="sinfo_calc_flow_depth" operator="equal"/>
+        </transition>
+
+        <state id="state.sinfo.distance_only" description="state.sinfo.distance_only" state="org.dive4elements.river.artifacts.states.DistanceOnlySelect" helpText="help.state.sinfo.distance_only">
+            <data name="ld_from" type="Double" />
+            <data name="ld_to"   type="Double" />
+        </state>
+
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.sinfo.distance_only"/>
+            <to state="state.sinfo.waterlevel_soundings_select"/>
+            <condition data="calculation_mode" value="sinfo_calc_flow_depth" operator="equal"/>
+        </transition>
+
+        <state id="state.sinfo.waterlevel_soundings_select" description="state.sinfo.waterlevel_soundings_select" state="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthPairSelectState" helpText="help.state.sinfo.waterlevel_soundings_select">
+            <data name="diffids" type="String" />
+        </state>
+
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.sinfo.waterlevel_soundings_select"/>
+            <to state="state.sinfo.use_transport_bodies"/>
+            <condition data="calculation_mode" value="sinfo_calc_flow_depth" operator="equal"/>
+        </transition>
+
+        <!-- FIXME: Nur Anzeigen, wenn Transportkörperhöhen vorliegen! -->
+        <state id="state.sinfo.use_transport_bodies" description="state.sinfo.use_transport_bodies" state="org.dive4elements.river.artifacts.sinfo.flowdepth.UseTransportBodiesChoice" helpText="help.state.sinfo.use_transport_bodies">
+            <data name="use_transport_bodies" type="Boolean" />
+        </state>
+
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.sinfo.use_transport_bodies"/>
+            <to state="state.sinfo.flow_depth"/>
+            <condition data="calculation_mode" value="sinfo_calc_flow_depth" operator="equal"/>
+        </transition>
+
+        <state id="state.sinfo.flow_depth" description="state.sinfo.flow_depth" state="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthState" helpText="help.state.sinfo.flow_depth">
+            <outputmodes>
+                <outputmode name="sinfo_flow_depth" description="output.flow_velocity" mime-type="image/png" type="chart">
+                    <facets>
+                        <!-- REMARK: id's that ends with 'filtered' are handled differently ' -->
+                        <facet name="sinfo_flow_depth.filtered" description="Facet for mean flow depth, filtered by current zoom state"/>
+
+                        <!-- 
+                        <facet name="flow_velocity.totalchannel" description="A facet for total channels"/>
+                        <facet name="flow_velocity.mainchannel" description="A facet for main channels"/>
+                        <facet name="flow_velocity.mainchannel" description="A facet for main channels"/>
+                        <facet name="flow_velocity.tau" description="A facet for tau"/>
+                        <facet name="flow_velocity.totalchannel.filtered" description="A facet for total channels"/>
+                        <facet name="flow_velocity.mainchannel.filtered" description="A facet for main channels"/>
+                        <facet name="flow_velocity.tau.filtered" description="A facet for tau"/>
+                        <facet name="flow_velocity.discharge" description="A facet for discharges"/>
+                        <facet name="flow_velocity.measurement" description="A facet for measured flow velocities"/>
+                        <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations"/>
+                        <facet name="flow_velocity.manualpoints"/>
+                        <facet name="bed_longitudinal_section.diameter.toplayer"/>
+                        <facet name="bed_longitudinal_section.diameter.sublayer"/>
+                        <facet name="bed_longitudinal_section.diameter.bedload"/>
+                         -->
+                    </facets>
+                </outputmode>
+
+                <outputmode name="sinfo_flowdepth_export" description="output.sinfo_flowdepth_export" mime-type="text/plain" type="export">
+                  <facets>
+                    <facet name="csv" description="facet.sinfo_flowdepth_export.csv" />
+                    <facet name="pdf" description="facet.sinfo_flowdepth_export.pdf" />
+                  </facets>
+                </outputmode>
+
+                <outputmode name="sinfo_flowdepth_report" description="output.sinfo_flowdepth_report" mime-type="text/xml" type="report">
+                  <facets>
+                    <facet name="report" description="facet.sinfo_flowdepth_report"/>
+                  </facets>
+                </outputmode>
+
+            </outputmodes>
+        </state>        
+
+    </states>
+
+</artifact>
\ No newline at end of file
--- a/artifacts/doc/conf/conf.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/conf.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -22,6 +22,8 @@
     <!ENTITY sqrelation-defaults SYSTEM "generators/sqrelation-diagram-defaults.xml">
     <!ENTITY longitudinal-defaults SYSTEM "generators/longitudinal-diagram-defaults.xml">
     <!ENTITY discharge-defaults SYSTEM "generators/discharge-diagram-defaults.xml">
+
+    <!ENTITY sinfo_artifact SYSTEM "artifacts/sinfo.xml">    
 ]>
 <artifact-database>
     <export-secret>YOUR_SECRET</export-secret>
@@ -168,6 +170,12 @@
             <artifact-factory name="porosity" description="Factory to create an artifact to show porosity values."
                 ttl="3600000"
                 artifact="org.dive4elements.river.artifacts.D4EArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+                
+            <!-- SINFO specific Artifacts -->
+            <artifact-factory name="sinfo" description="Factory to create an artifact to be used in module sinfo."
+                ttl="3600000"
+                artifact="org.dive4elements.river.artifacts.sinfo.SINFOArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+                
         </artifact-factories>
 
         <user-factory name="default" description="Factory to create new users">org.dive4elements.artifactdatabase.DefaultUserFactory</user-factory>
@@ -299,6 +307,8 @@
         &gaugedischargecurve-artifact;
         &sedimentload-artifact;
         &sedimentload-ls-artifact;
+       
+        &sinfo_artifact;
     </artifacts>
 
     &modules;
--- a/artifacts/doc/conf/generators/generators.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/generators/generators.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -58,5 +58,10 @@
     <output-generator names="gauge_discharge_curve_at_export" class="org.dive4elements.river.exports.ATExporter"/>
     <output-generator names="fix_wq_curve_at_export" class="org.dive4elements.river.exports.fixings.FixATExport"/>
     <output-generator names="wsplgen" class="org.dive4elements.river.exports.ShapeExporter"/>
+    
+    <!-- SINFO -->
+    <output-generator names="sinfo_flowdepth_report" class="org.dive4elements.river.exports.ReportGenerator"/>
+    <output-generator names="sinfo_flowdepth_export" class="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthExporter"/>
+
 </output-generators>
 
--- a/artifacts/doc/conf/generators/longitudinal-diagram-defaults.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/generators/longitudinal-diagram-defaults.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -14,8 +14,8 @@
     <axis name="Velocity"/>
     <axis name="Tau"/>
     <axis name="Q" include-zero="true"/>
-    <domain-axis key="chart.longitudinal.section.xaxis.label" default="Fluss-Km"
-            inverted="org.dive4elements.river.exports.IsKmUpEvaluator()">
+    <axis name="Flowdepth" />
+    <domain-axis key="chart.longitudinal.section.xaxis.label" default="Fluss-Km" inverted="org.dive4elements.river.exports.IsKmUpEvaluator()">
         <arg expr="artifact.river"/>
     </domain-axis>
     <!-- Default longitudinal section Processors -->
@@ -42,4 +42,7 @@
     <processor class="org.dive4elements.river.exports.process.ShearStressProcessor"        axis="Tau"/>
     <processor class="org.dive4elements.river.exports.process.SedimentDensityProcessor"    axis="Density"/>
     <processor class="org.dive4elements.river.exports.process.BedHeightProcessor"          axis="W"/>
-</longitudinal-defaults>
+
+    <!-- S-INFO -->
+    <processor class="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthProcessor" axis="Flowdepth"/>
+</longitudinal-defaults>
\ No newline at end of file
--- a/artifacts/doc/conf/generators/longitudinal-diagrams.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/generators/longitudinal-diagrams.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -87,5 +87,20 @@
             <arg expr="artifact.river"/>
         </subtitle>
     </output-generator>
-</longitudinal-diagrams>
 
+<!--
+,flow_velocity_chartinfo 
+ -->
+    <output-generator
+        names="sinfo_flow_depth,sinfo_flow_depth_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flow_depth.section.title" default="h-Längsschnitt (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="FlowDepth"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+</longitudinal-diagrams>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/FIXME.txt	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,6 @@
+Awful:
+- source files together with compiled files in one directory
+- source files part of 'conf', but user will probably never be able to conf them
+- compiled files checked-in into SCM
+- compilation process not part of maven (not even part of project at all)
+- we have different jasper reports for different languages; instead introduce variables and give i10n strings as report variables
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.flowdepth.jrxml	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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="515" leftMargin="60" 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"/>
+
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range" 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"/>
+	<field name="data:7" class="java.lang.String"/>
+	<field name="data:8" class="java.lang.String"/>
+	<field name="data:9" class="java.lang.String"/>
+	<field name="data:10" class="java.lang.String"/>
+	<field name="data:11" class="java.lang.String"/>
+-->
+
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="182" splitType="Stretch">
+			<staticText>
+				<reportElement x="0" y="1" width="165" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<text><![CDATA[Ergebnisausgabe]]></text>
+			</staticText>
+			<!--
+			<textField>
+				<reportElement x="165" y="0" width="350" height="31"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="165" y="0" width="350" height="31"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="165" y="0" width="350" height="31"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="31" width="515" height="26"/>
+				<textElement>
+					<font size="14"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{calculation}]]></textFieldExpression>
+			</textField>
+			-->
+			
+			<staticText>
+				<reportElement x="0" y="70" width="123" height="20"/>
+				<textElement/>
+				<text><![CDATA[FLYS-Version:]]></text>
+			</staticText>
+			<textField>
+				<reportElement x="123" y="70" width="392" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			
+			<staticText>
+				<reportElement x="0" y="90" width="123" height="20"/>
+				<textElement/>
+				<text><![CDATA[Bearbeiter:]]></text>
+			</staticText>
+			<textField>
+				<reportElement x="123" y="90" width="392" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			
+			<staticText>
+				<reportElement x="0" y="110" width="123" height="20"/>
+				<textElement/>
+				<text><![CDATA[Datum der Erstellung:]]></text>
+			</staticText>
+			<textField>
+				<reportElement x="123" y="110" width="392" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			
+			<staticText>
+				<reportElement x="0" y="130" width="123" height="20"/>
+				<textElement/>
+				<text><![CDATA[Gewässer:]]></text>
+			</staticText>
+			<textField>
+				<reportElement x="123" y="130" width="392" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			
+			<staticText>
+				<reportElement x="0" y="150" width="123" height="20"/>
+				<textElement/>
+				<text><![CDATA[Bereich:]]></text>
+			</staticText>
+			<textField>
+				<reportElement x="123" y="150" width="392" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement x="0" y="19" width="515" height="1"/>
+			</line>
+			<staticText>
+				<reportElement x="0" y="0" width="60" height="20"/>
+				<textElement/>
+				<text><![CDATA[Fluss-Km]]></text>
+			</staticText>
+			<staticText>
+				<reportElement x="60" y="0" width="65" height="20"/>
+				<textElement/>
+				<text><![CDATA[W [NN + m]]]></text>
+			</staticText>
+			<staticText>
+				<reportElement x="125" y="0" width="65" height="20"/>
+				<textElement/>
+				<text><![CDATA[Q [m³/s]]]></text>
+			</staticText>
+			<staticText>
+				<reportElement x="190" y="0" width="85" height="20"/>
+				<textElement/>
+				<text><![CDATA[Bezeichnung]]></text>
+			</staticText>
+			<staticText>
+				<reportElement x="275" y="0" width="110" height="20"/>
+				<textElement/>
+				<text><![CDATA[Lage]]></text>
+			</staticText>
+			<staticText>
+				<reportElement x="385" y="0" width="130" height="20"/>
+				<textElement/>
+				<text><![CDATA[Bezugspegel]]></text>
+			</staticText>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="14" splitType="Stretch">
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="0" width="60" height="14"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="60" y="0" width="65" height="14"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="125" y="0" width="65" height="14"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="false">
+				<reportElement stretchType="RelativeToBandHeight" x="190" y="0" width="85" height="14"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement stretchType="RelativeToBandHeight" x="275" y="0" width="110" height="14" isPrintWhenDetailOverflows="true"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement stretchType="RelativeToBandHeight" x="385" y="0" width="130" height="14"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="29" splitType="Stretch">
+			<textField evaluationTime="Report">
+				<reportElement x="458" y="9" width="57" height="20"/>
+				<textElement/>
+				<textFieldExpression><![CDATA[" / " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="403" y="9" width="55" height="20"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="42" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- a/artifacts/doc/conf/meta-data.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/meta-data.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -242,6 +242,19 @@
                   <dc:when test="$out = 'floodmap'">
                     <dc:call-macro name="flood-map-complete"/>
                   </dc:when>
+
+                  <dc:comment> S-INFO </dc:comment>
+                  <dc:when test="$out = 'sinfo_flowdepth_minfo_heights'">
+                    <dc:call-macro name="bed-heights-single"/>
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flowdepth_waterlevels'">
+                    <!-- FIXME: check requirement what to show here... -->
+                    <dc:call-macro name="basedata_0"/>
+                    <dc:call-macro name="basedata_1_additionals"/>
+                    <dc:call-macro name="basedata_2_fixations"/>
+                    <dc:call-macro name="basedata_4_heightmarks-points"/>
+                    <dc:call-macro name="basedata_5_flood-protections"/>
+                  </dc:when>
                 </dc:choose>
               </dc:iterate>
             </dc:otherwise>
--- a/artifacts/doc/conf/modules.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/modules.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -3,6 +3,9 @@
   <module name="winfo" selected="true">
     <river name="Beispielfluss"/>
   </module>
+  <module name="sinfo">
+    <river name="Beispielfluss"/>
+  </module>
   <module name="minfo">
     <river name="Beispielfluss"/>
   </module>
@@ -15,5 +18,4 @@
   <module name="fixanalysis">
     <river name="Beispielfluss"/>
   </module>
-</modules>
-
+</modules>
\ No newline at end of file
--- a/artifacts/doc/conf/themes.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/themes.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -404,6 +404,8 @@
 
         <!-- Mappings for porosity from backend-DB -->
         <mapping from="porosity" to="Porosity" />
+
+        <!--  Mappings for S-INFO -->
+        <mapping from="sinfo_flow_depth.filtered" to="SInfoFlowDepth" />
     </mappings>
-
-</themes>
+</themes>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/default.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/themes/default.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -2872,4 +2872,16 @@
             <field name="linecolor" type="color" default="175, 175, 175" />
         </fields>
     </theme>
+
+    <!-- S-INFO Flow-Depth Themes -->
+    <theme name="SInfoFlowDepth">
+        <inherits>
+            <inherit from="LongitudinalSection" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe"
+                default="0, 0, 255" />
+        </fields>
+    </theme>
+    
 </themegroup>
--- a/artifacts/doc/conf/themes/second.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/doc/conf/themes/second.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -2869,4 +2869,15 @@
             <field name="linecolor" type="color" default="175, 175, 175" />
         </fields>
     </theme>
-</themegroup>
+    
+    <!-- S-INFO Flow-Depth Themes -->
+    <theme name="SInfoFlowDepth">
+        <inherits>
+            <inherit from="LongitudinalSection" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe"
+                default="0, 0, 255" />
+        </fields>
+    </theme>
+</themegroup>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/CalculationSelectSinfo.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,76 @@
+/* Copyright (C) 2017 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.artifacts.sinfo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/**
+ * @author Gernot Belger
+ */
+public class CalculationSelectSinfo extends DefaultState {
+
+	private static final long serialVersionUID = 1L;
+
+	/** The log that is used in this class. */
+    private static Logger log = Logger.getLogger(CalculationSelectSinfo.class);
+
+    public CalculationSelectSinfo() {
+    }
+
+
+    @Override
+    protected Element[] createItems(
+        XMLUtils.ElementCreator cr,
+        Artifact    artifact,
+        String      name,
+        CallContext context)
+    {
+        final CallMeta meta   = context.getMeta();
+        
+        final Collection<Element> calcs = new ArrayList<>(SinfoCalcMode.values().length);
+
+        for (final SinfoCalcMode calcMode : SinfoCalcMode.values()) {
+        	final String calc = calcMode.name();
+        	
+        	final String label = Resources.getMsg(meta, calc, calc);
+        	
+        	final Element element = createItem(
+        			cr, new String[] {
+        					label,
+        					calc
+        			});
+        	calcs.add(element);
+		}
+        
+        return calcs.toArray(new Element[calcs.size()]);
+    }
+
+    @Override
+    public boolean validate(Artifact artifact)
+    throws IllegalArgumentException
+    {
+        log.debug("CalculationSelect.validate");
+
+        final SINFOArtifact sinfo = (SINFOArtifact) artifact;
+        /* throws an exception if calculation mode is invalid */
+        sinfo.getCalculationMode();
+        return true;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/SINFOArtifact.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,73 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.river.artifacts.D4EArtifact;
+
+/**
+ * The default MINFO artifact.
+ *
+ * @author Gernot Belger
+ */
+public class SINFOArtifact
+extends      D4EArtifact
+{
+    /** Error message that is thrown if no mode has been chosen. */
+    private static final String ERROR_NO_CALCULATION_MODE =
+        "error_feed_no_calculation_mode";
+
+    /** Error message that is thrown if an invalid calculation mode has been
+     * chosen. */
+    private static  final String ERROR_INVALID_CALCULATION_MODE =
+        "error_feed_invalid_calculation_mode";
+
+	
+    /** The name of the artifact. */
+    private static final String ARTIFACT_NAME = "sinfo";
+
+    private static final String FIELD_FIVER = "river";
+
+    private static final String FIELD_MODE = "calculation_mode";
+    
+    /**
+     * Default constructor, because it's serializable.
+     */
+    public SINFOArtifact() {
+    }
+
+    /**
+     * Returns the name of the concrete artifact.
+     *
+     * @return the name of the concrete artifact.
+     */
+    @Override
+    public String getName() {
+        return ARTIFACT_NAME;
+    }
+    
+    public SinfoCalcMode getCalculationMode() {
+
+        final String    calc = getDataAsString(FIELD_MODE);
+        if (calc == null) {
+        	throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE);
+        }
+
+        try {
+			return SinfoCalcMode.valueOf(StringUtils.trimToEmpty(calc).toLowerCase());
+		} catch (Exception e) {
+			throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE, e);
+		}
+	}
+    
+    public String getRiver() {
+    	return getDataAsString(FIELD_FIVER);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/SinfoCalcMode.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,20 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo;
+
+public enum SinfoCalcMode{
+	sinfo_calc_flow_depth,
+	sinfo_calc_flow_depth_development,
+    sinfo_calc_flow_depth_minmax,
+    sinfo_calc_grounding,
+    sinfo_calc_transport_bodies_heights,
+    sinfo_calc_infrastructures_inundation_duration
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthAccess.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,88 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.SinfoCalcMode;
+import org.dive4elements.river.backend.utils.StringUtil;
+
+/**
+ * Access to the flow depth calculation type specific SInfo artifact data.
+ * REMARK: this class is NOT intended to be hold in the results (or anywhere else), in order to avoid a permanent reference to the artifact instance. 
+ * Hence we do NOT cache any data.
+ * 
+ * @author Gernot Belger
+ */
+public class FlowDepthAccess
+extends      RangeAccess
+{
+	public static class DifferencesPair
+	{
+		private final String wstId;
+		private final String soundingId;
+
+		public DifferencesPair( final String wstId, final String soundingId ) {
+			this.wstId = wstId;
+			this.soundingId = soundingId;
+		}
+		
+		public String getWstId() {
+			return this.wstId;
+		}
+
+		public String getSoundingId() {
+			return this.soundingId;
+		}
+	}
+
+	private static final String FIELD_USE_TKH = "use_transport_bodies"; //$NON-NLS-1$
+
+	public FlowDepthAccess(final SINFOArtifact artifact) {
+		super(artifact);
+
+		/* assert calculation mode */
+		final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+		assert(calculationMode == SinfoCalcMode.sinfo_calc_flow_depth);
+	}
+
+	public boolean isUseTransportBodies() {
+		final Boolean useTkh = artifact.getDataAsBoolean( FIELD_USE_TKH );
+		return useTkh == null ? false : useTkh;
+	}
+
+	public Collection<DifferencesPair> getDifferencePairs() {
+
+		final Collection<DifferencesPair> diffPairs = new ArrayList<>();
+
+		 final String diffids = super.getString("diffids");
+		 if( diffids == null )
+		 {
+			 // Should never happen as this is handled by the ui
+			 return Collections.emptyList();
+		 }
+
+		 // FIXME: this way of parsing the datacage-ids is repeated all over flys!
+		 final String datas[] = diffids.split("#");
+		 for(int i = 0; i < datas.length; i+=2) {
+			 final String leftId = StringUtil.unbracket( datas[i] );
+			 final String rightId = StringUtil.unbracket( datas[i+1] );
+
+			 diffPairs.add(new DifferencesPair(leftId, rightId));
+		 }
+
+		return Collections.unmodifiableCollection(diffPairs);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,152 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.BedHeightsArtifact;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.LocationProvider;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair;
+import org.dive4elements.river.artifacts.states.WDifferencesState;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.utils.GaugeIndex;
+import org.dive4elements.river.utils.RiverUtils;
+
+class FlowDepthCalculation {
+
+    private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range";
+
+	private CallContext context;
+
+	public FlowDepthCalculation( final CallContext context ) {
+		this.context = context;
+	}
+	
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+    	
+    	/* access input data */
+    	final FlowDepthAccess access = new FlowDepthAccess(sinfo);
+    	final River river = access.getRiver();
+    	
+    	final Collection<DifferencesPair> diffPairs = access.getDifferencePairs();
+    	
+		final double from = access.getFrom();
+		final double to = access.getTo();
+
+    	final boolean useTkh = access.isUseTransportBodies();
+
+    	/* calculate results for each diff pair */
+    	final Calculation problems = new Calculation();
+
+    	final List<Gauge> gauges = river.determineGauges(from, to);
+    	final GaugeIndex gaugeIndex = new GaugeIndex(gauges);
+
+    	final FlowDepthCalculationResults results = new FlowDepthCalculationResults(river, from, to, useTkh);
+
+    	for (final DifferencesPair diffPair : diffPairs) {
+    		final FlowDepthCalculationResult result = calculateResult( river, from, to, diffPair, problems, gaugeIndex );
+    		if( result != null )
+    			results.addResult(result);
+		}
+    	
+		return new CalculationResult(results,problems);
+    }
+
+	private FlowDepthCalculationResult calculateResult(final River river, final double from, final double to, final DifferencesPair diffPair, final Calculation problems, final GaugeIndex gaugeIndex) {
+
+		/* access real input data from database */
+    	final String soundingId = diffPair.getSoundingId();
+    	final String wstId = diffPair.getWstId();
+
+    	final BedHeight bedHeight = loadBedHeight( soundingId, from, to );
+		final WKms wstKms = new WDifferencesState().getWKms(wstId, context, from, to);
+		if( bedHeight == null || wstKms == null )
+			return null;
+
+    	final FlowDepthCalculationResult resultData = new FlowDepthCalculationResult(wstKms.getName(), bedHeight.getDescription());
+
+        final String notinrange = Resources.getMsg(context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE);
+
+    	// TODO: unklarheiten
+    	// 'idealerweise alle 100m' was heisst das? kann doch nur durch datenverfügbarkeit bestimmt werden
+    	// wie mit unterschiedlichen Ranges umgehen? Schnitt bilden? Fehlermeldung? ...?
+    	// wie interpolieren? wst interpolieren? peilung interpolieren?
+
+		// FIXME: für die Berechnung der TKH sind weitere 'in FLYS vorliegende' Daten notwendig.
+		// aktuell unklar ob das durch andere Barten berechnete Werte oder Basisdaten sind
+		// TODO: check Vergleiche BArt 'Transportkörperhöhen'
+        
+    	// TODO: Berechnung der Transportkörperhöhen
+    	// - woher kommen die zusätzlichen eingangsdaten? sind das fixe daten pro gewässer? --> falls ja, warum nicht einmal berechnen und in db ablegen?
+
+    	final String bedHeightLabel = bedHeight.getDescription();
+    	final String wstLabel = wstKms.getName();
+
+		for (int i = 0; i < wstKms.size(); i++) {
+
+			final double km = wstKms.getKm(i);
+    		final double wst = wstKms.getW(i);
+    		// FIXME: interpolate from bedheights?
+    		final double meanBedHeight = 79.32;
+
+    		final double flowDepth = wst - meanBedHeight;
+    		
+    		final double tkh = 0;
+    		final double flowDepthTkh = flowDepth - tkh;
+    		
+    		// FIXME: discharge not available for all wst? or any?
+    		final double discharge = 0.0;
+
+    		// REMARK: access the location once only during calculation 
+    		final String location = LocationProvider.getLocation(river.getName(), km);
+    		
+    		// REMARK: access the gauge once only during calculation 
+    		final Gauge gauge = gaugeIndex.findGauge(km);
+    		final String gaugeLabel = gauge == null ? notinrange : gauge.getName();
+    		
+			resultData.addRow( km, flowDepth, flowDepthTkh, tkh, wst, discharge, wstLabel, gaugeLabel, meanBedHeight, bedHeightLabel, location );
+		}
+		
+		return resultData;
+	}
+
+	private BedHeight loadBedHeight(final String soundingId, final double from, final double to) {
+		
+		// FIXME: absolutely unbelievable....
+		// The way how bed-heights (and other data too) is accessed is different for nearly ever calculation-type throughout flys.
+		// The knowledge on how to parse the datacage-ids is spread thorugh the complete code-base...
+
+		// We use here the way on how bed-heights are accessed by the BedDifferenceAccess/BedDifferenceCalculation, but this is plain random
+	    final String[] parts = soundingId.split(";");
+
+	    final BedHeightsArtifact artifact = (BedHeightsArtifact) RiverUtils.getArtifact(parts[0], context);
+
+	    final Integer bedheightId = artifact.getDataAsInteger("height_id");
+	    // FIXME: this only works with type 'single'; unclear on how to distinguish from epoch data (or whatever the other type means)
+	    // Luckily, the requirement is to only access 'single' data here.
+	    // final String bedheightType = artifact.getDataAsString("type");
+	    
+	    // FIXME: BedDifferences uses this, but we also need the metadata of the BedHeight
+	    // FIXME: second absolutely awful thing: BedHeight is a hibernate binding class, accessing the database via hibernate stuff
+	    // BedHeightFactory uses its own (direct) way of accessing the data, with its own implemented data classes.
+	    //return BedHeightFactory.getHeight(bedheightType, bedheightId, from, to);
+	     
+	    return BedHeight.getBedHeightById(bedheightId);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculationResult.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,68 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Contains the results of a {@link FlowDepthCalculation}.
+ *
+ * @author Gernot Belger
+ */
+class FlowDepthCalculationResult
+implements Serializable {
+	
+	private static final long serialVersionUID = 1L;
+
+	private final Collection<FlowDepthRow> rows = new ArrayList<>();
+
+	private final String wstLabel;
+	
+	private final String soundingLabel;
+
+	public FlowDepthCalculationResult(final String wstLabel, final String soundingLabel) {
+		this.wstLabel = wstLabel;
+		this.soundingLabel = soundingLabel;
+	}
+
+	public void addRow(double station, double flowDepth, double flowDepthWithTkh, double tkh, double waterlevel, double discharge, String waterlevelLabel, String gauge, double meanBedHeight, String sondageLabel, String location) {
+		rows.add(new FlowDepthRow(station, flowDepth, flowDepthWithTkh, tkh, waterlevel, discharge, waterlevelLabel, gauge, meanBedHeight, sondageLabel, location));
+	}
+	
+	public String getWstLabel() {
+		return this.wstLabel;
+	}
+
+	public String getSoundingLabel() {
+		return this.soundingLabel;
+	}
+
+	public Collection<FlowDepthRow> getRows() {
+		return  Collections.unmodifiableCollection( rows );
+	}
+	
+    public double[][] getFlowDepthPoints() {
+
+    	TDoubleArrayList xPoints = new TDoubleArrayList(rows.size());
+    	TDoubleArrayList yPoints = new TDoubleArrayList(rows.size());
+    	
+        for (FlowDepthRow row : rows) {
+        	xPoints.add(row.getStation());
+			yPoints.add(row.getFlowDepth());
+		}
+        
+        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculationResults.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,63 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+public class FlowDepthCalculationResults{
+	private final List<FlowDepthCalculationResult> results = new ArrayList<>();
+
+	private final River river;
+	
+	private final double from;
+	
+	private final double to;
+	
+	private final boolean useTkh;
+
+	public FlowDepthCalculationResults(final River river, final double from, final double to, final boolean useTkh) {
+		this.river = river;
+		this.from = from;
+		this.to = to;
+		this.useTkh = useTkh;
+	}
+	
+	public River getRiver() {
+		return this.river;
+	}
+
+	public double getFrom() {
+		return this.from;
+	}
+
+	public double getTo() {
+		return this.to;
+	}
+
+	public boolean isUseTkh() {
+		return this.useTkh;
+	}
+	
+	void addResult(final FlowDepthCalculationResult result) {
+		results.add(result);
+	}
+	
+	public List<FlowDepthCalculationResult> getResults() {
+		return Collections.unmodifiableList(results);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthExporter.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,449 @@
+/* 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.artifacts.sinfo.flowdepth;
+
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.Config;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.MetaAndTableJRDataSource;
+import org.dive4elements.river.exports.AbstractExporter;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.utils.Formatter;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import net.sf.jasperreports.engine.JRDataSource;
+import net.sf.jasperreports.engine.JRException;
+import net.sf.jasperreports.engine.JasperExportManager;
+import net.sf.jasperreports.engine.JasperFillManager;
+import net.sf.jasperreports.engine.JasperPrint;
+
+/**
+ * Generates different output formats (csv, pdf) of data that resulted from a flow depths computation.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ * @author Gernot Belger
+ */
+// REMARK: must be public because its registered in generators.xml
+public class FlowDepthExporter extends AbstractExporter {
+
+    /** The log used in this exporter.*/
+    private static Logger log = Logger.getLogger(FlowDepthExporter.class);
+
+    private static final String CSV_KM_HEADER = "sinfo.export.flow_depth.csv.header.km";
+    private static final String CSV_FLOWDEPTH_HEADER = "sinfo.export.flow_depth.csv.header.flowdepth";
+    private static final String CSV_FLOWDEPTHTKH_HEADER = "sinfo.export.flow_depth.csv.header.flowdepthTkh";
+    private static final String CSV_TKH_HEADER = "sinfo.export.flow_depth.csv.header.tkh";
+    private static final String CSV_WATERLEVEL_HEADER = "sinfo.export.flow_depth.csv.header.waterlevel";
+    private static final String CSV_DISCHARGE_HEADER = "sinfo.export.flow_depth.csv.header.discharge";
+    private static final String CSV_LABEL_HEADER = "sinfo.export.flow_depth.csv.header.label";
+    private static final String CSV_GAUGE_HEADER = "sinfo.export.flow_depth.csv.header.gauge";
+    private static final String CSV_MEAN_BED_HEIGHT_HEADER = "sinfo.export.flow_depth.csv.header.mean_bed_height";
+    private static final String CSV_SOUNDING_HEADER = "sinfo.export.flow_depth.csv.header.sounding";
+    private static final String CSV_LOCATION_HEADER = "sinfo.export.flow_depth.csv.header.location";
+    
+    private static final String CSV_META_HEADER_RESULT =
+        "sinfo.export.flow_depth.csv.meta.header.result";
+
+    private static final String CSV_META_VERSION =
+    		"sinfo.export.flow_depth.csv.meta.version";
+    
+    private static final String CSV_META_USER =
+    		"sinfo.export.flow_depth.csv.meta.user";
+    
+    private static final String CSV_META_CREATION =
+        "sinfo.export.flow_depth.csv.meta.creation";
+
+    private static final String CSV_META_RIVER =
+        "sinfo.export.flow_depth.csv.meta.river";
+
+    private static final String CSV_META_HEADER_SOUNDING =
+    		"sinfo.export.flow_depth.csv.meta.header.sounding";
+
+    private static final String CSV_META_HEADER_WATERLEVEL =
+    		"sinfo.export.flow_depth.csv.meta.header.waterlevel";
+    
+    private static final String JASPER_FILE     = "/jasper/sinfo.flowdepth.jasper"; //$NON-NLS-1$
+
+    /** The storage that contains the current calculation result.*/
+    private FlowDepthCalculationResults data = null;
+
+	private NumberFormat meanBedHeightFormatter;
+
+	private NumberFormat tkhFormatter;
+
+	private NumberFormat flowDepthFormatter;
+
+    private NumberFormat getMeanBedHeightFormatter() {
+    	if( meanBedHeightFormatter == null )
+    		// FIXME: check if this is right
+    		meanBedHeightFormatter = Formatter.getMiddleBedHeightHeight(context);
+		return meanBedHeightFormatter;
+	}
+
+	private NumberFormat getTkhFormatter() {
+    	if( tkhFormatter == null )
+    		// FIXME: check if this is right, probably not, we need one digit
+    		tkhFormatter = Formatter.getWaterlevelW(context);
+		return tkhFormatter;
+	}
+
+	private NumberFormat getFlowDepthFormatter() {
+    	if( flowDepthFormatter == null )
+    		// FIXME: check if this is right
+    		flowDepthFormatter = Formatter.getMeterFormat(context);
+		return flowDepthFormatter;
+	}    
+    
+    @Override
+    protected void addData(Object d) {
+    	/* reset */
+    	data = null;
+
+        if (d instanceof CalculationResult) {
+
+        	final Object dat = ((CalculationResult)d).getData();
+        	if( dat != null )
+        		data = (FlowDepthCalculationResults)dat;
+        }
+    }
+
+    @Override
+    protected void writeCSVData(CSVWriter writer) {
+        log.info("FlowDepthExporter.writeCSVData");
+
+        /* fetch calculation results */
+        final FlowDepthCalculationResults results = data;
+
+        /* write as csv */
+
+//        boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
+//        boolean isQ     = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
+//        RiverUtils.WQ_INPUT input
+//            = RiverUtils.getWQInputMode((D4EArtifact)master);
+
+        final boolean useTkh = results.isUseTkh();
+
+        writeCSVMeta(writer, results);
+        writeCSVHeader(writer, useTkh);
+
+        for (final FlowDepthCalculationResult result : results.getResults()) {
+        	writeCSVFlowDepthResult(writer, result, useTkh);
+		}
+    }
+
+    private void writeCSVFlowDepthResult(final CSVWriter writer, final FlowDepthCalculationResult result, final boolean useTkh) {
+        final Collection<FlowDepthRow> rows = result.getRows();
+        for (final FlowDepthRow flowDepthRow : rows) {
+        	writeCSVFlowDepthRow(writer, flowDepthRow, useTkh);
+		}
+	}
+
+	private void writeCSVMeta(final CSVWriter writer, final FlowDepthCalculationResults results) {
+        log.info("FlowDepthExporter.writeCSVMeta");
+
+        // Workflow zur Berechnung der Fließtiefe.pdf
+        // "##ERGEBNISAUSGABE - Name des Gewässers - Fließtiefe"
+        final River river = results.getRiver();
+		writeCSVMeataEntry(writer, CSV_META_HEADER_RESULT, river.getName() );
+
+		// "# FLYS-Version: "
+        // FIXME
+        final String flysVersion = "unbekannt";
+        writeCSVMeataEntry(writer, CSV_META_VERSION, flysVersion );
+
+		// "# Bearbeiter: "
+        // FIXME
+        final String user = "unbekannt";
+        writeCSVMeataEntry(writer, CSV_META_USER, user );
+
+        // "# Datum der Erstellung: "
+        final Locale locale = Resources.getLocale(context.getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        writeCSVMeataEntry(writer, CSV_META_CREATION, df.format(new Date()) );
+
+        // "# Gewässer: "
+        writeCSVMeataEntry(writer, CSV_META_RIVER, river.getName() );
+
+        // "# Höhensystem des Flusses: "
+        
+        // FIXME
+
+        // "# Ort/Bereich (km): "
+        // FIXME
+        // TODO: unklar, es wird nur ein Bereich eingegeben
+//        RangeAccess rangeAccess = new RangeAccess(flys);
+//        double[] kms = rangeAccess.getKmRange();
+//        writer.writeNext(new String[] {
+//        		Resources.getMsg(
+//        				meta,
+//        				CSV_META_RANGE,
+//        				CSV_META_RANGE,
+//        				new Object[] { kms[0], kms[kms.length-1] })
+//        });
+
+        // "##METADATEN PEILUNG"
+        writeCSVMeataEntry(writer, CSV_META_HEADER_SOUNDING );
+
+//        "# Jahr der Peilung: "
+        // FIXME
+//        "# Aufnahmeart: "
+        // FIXME
+//        "# Lagesystem: "
+        // FIXME
+//        "# Höhensystem: "
+        // FIXME
+//        "# ursprüngliches Höhensystem: "
+        // FIXME
+//        "##METADATEN WASSERSPIEGELLAGE"
+        writeCSVMeataEntry(writer, CSV_META_HEADER_WATERLEVEL );
+//        "# Bezeichnung der Wasserspiegellage: "
+        // FIXME
+//        "# Höhensystem der Wasserspiegellage: "
+        // FIXME
+//        "# Auswerter: "
+        // FIXME
+//        "# Bezugspegel: "
+        // FIXME
+//        "# Jahr/Zeitraum der Wasserspiegellage: "
+        // FIXME
+
+        // "# W/Pegel [cm]: " (nur bei Eingabe des Wasserstands am Pegel)
+        // TODO: unklar, es wird kein W eingegeben
+
+        // "# Q (m³/s): " (nur bei Eingabe des Durchflusses)        
+        // TODO: unklar, es wird kein Q eingegeben
+
+//        writer.writeNext(new String[] {
+//            Resources.getMsg(
+//                meta,
+//                CSV_META_GAUGE,
+//                CSV_META_GAUGE,
+//                new Object[] { RiverUtils.getGaugename(flys) })
+//        });
+
+        writer.writeNext(new String[] { "" });
+    }
+
+
+    private void writeCSVMeataEntry(CSVWriter writer, String message, Object... messageArgs) {
+
+        CallMeta meta = context.getMeta();
+
+        writer.writeNext(new String[] {
+                Resources.getMsg(
+                    meta,
+                    message,
+                    message,
+                    messageArgs)
+            });		
+    }
+    
+	/**
+     * Write the header, with different headings depending on whether at a
+     * gauge or at a location.
+	 * @param useTkh 
+     */
+    private void writeCSVHeader(
+        final CSVWriter writer,
+        final boolean useTkh
+    ) {
+        log.info("FlowDepthExporter.writeCSVHeader");
+
+        final Collection<String> header = new ArrayList<>(11);
+        
+        header.add(msg(CSV_KM_HEADER,CSV_KM_HEADER));
+        header.add(msg(CSV_FLOWDEPTH_HEADER));
+        if( useTkh )
+        {
+        	header.add(msg(CSV_FLOWDEPTHTKH_HEADER));
+        	header.add(msg(CSV_TKH_HEADER));
+        }
+        header.add(msg(CSV_WATERLEVEL_HEADER));
+        header.add(msg(CSV_DISCHARGE_HEADER));
+        header.add(msg(CSV_LABEL_HEADER));
+        header.add(msg(CSV_GAUGE_HEADER));
+        header.add(msg(CSV_MEAN_BED_HEIGHT_HEADER));
+        header.add(msg(CSV_SOUNDING_HEADER));
+        header.add(msg(CSV_LOCATION_HEADER));
+
+       writer.writeNext(header.toArray(new String[header.size()]));
+    }
+
+    /**
+     * Format a row of a flow depth result into an array of string, both used by csv and pdf
+     * @param useTkh 
+     */
+    private String[] formatFlowDepthRow(
+    		final FlowDepthRow row, 
+    		boolean useTkh ) {
+
+    	final Collection<String> lines = new ArrayList<>(11);
+    	
+    	// Fluss-km
+    	lines.add( getKmFormatter().format( row.getStation() ) );
+    	
+    	// Fließtiefe [m]
+    	lines.add( getFlowDepthFormatter().format( row.getFlowDepth() ) );
+    	
+    	if( useTkh )
+    	{
+    		// Fließtiefe mit TKH [m]
+    		lines.add( getFlowDepthFormatter().format( row.getFlowDepthWithTkh() ) );
+    		
+    		// TKH [cm]
+    		lines.add( getTkhFormatter().format( row.getTkh() ) );
+    	}
+    	
+    	// Wasserstand [NN + m]
+    	lines.add( getWFormatter().format( row.getWaterlevel() ) );
+    	
+    	// Q [m³/s]
+    	lines.add( getQFormatter().format( row.getDischarge() ) );
+    	
+    	// Bezeichnung
+    	lines.add( row.getWaterlevelLabel() );
+    	
+    	// Bezugspegel
+    	lines.add( row.getGauge() );
+    	
+    	// Mittlere Sohlhöhe [NN + m]
+    	lines.add( getMeanBedHeightFormatter().format( row.getMeanBedHeight( ) ) );
+    	
+    	// Peilung/Epoche
+    	lines.add( row.getSoundageLabel() );
+
+    	// Lage
+    	lines.add( row.getLocation() );
+    	
+    	return lines.toArray(new String[lines.size()]);
+    }
+    /**
+     * Write "rows" of csv data from wqkms with writer.
+     * @param useTkh 
+     */
+    private void writeCSVFlowDepthRow(
+        final CSVWriter writer,
+        final FlowDepthRow row, 
+        final boolean useTkh
+    ) {
+        log.debug("FlowDepthExporter.writeCSVFlowDepthRow");
+
+        final String[] formattedRow = formatFlowDepthRow(row, useTkh);
+        writer.writeNext( formattedRow );
+    }
+
+	@Override
+    protected void writePDF(OutputStream outStream) {
+        log.debug("write PDF");
+        
+        final JRDataSource source = createJRData();
+
+        final String confPath = Config.getConfigDirectory().toString();
+
+        // FIXME: distinguish between with and without tkh: we need two jasper reports! 
+
+        final Map<String,Object> parameters = new HashMap<>();
+        parameters.put("ReportTitle", "Exported Data");
+        try {
+            final JasperPrint print = JasperFillManager.fillReport(
+                confPath + JASPER_FILE,
+                parameters,
+                source);
+            JasperExportManager.exportReportToPdfStream(print, outStream);
+        }
+        catch(JRException je) {
+            log.warn("Error generating PDF Report!", je);
+        }
+    }
+
+    private JRDataSource createJRData() {
+    	
+        /* fetch calculation results */
+        final FlowDepthCalculationResults results = data;
+    	
+    	final MetaAndTableJRDataSource source = new MetaAndTableJRDataSource();
+    	
+        addJRMetaData(source, results);
+
+        final boolean useTkh = results.isUseTkh();
+        
+        for (final FlowDepthCalculationResult result : results.getResults()) {
+			addJRTableData(source, result, useTkh);
+		}
+
+        return source;
+    }
+
+	private void addJRMetaData(final MetaAndTableJRDataSource source, FlowDepthCalculationResults results) {
+
+		// Workflow zur Berechnung der Fließtiefe.pdf
+        // "##ERGEBNISAUSGABE - Name des Gewässers - Fließtiefe"
+        // writeCSVMeataEntry(writer, CSV_META_HEADER_RESULT, inputData.getRiver() );
+        
+        // FIXME
+        final String flysVersion = "unbekannt";
+        // CSV_META_VERSION
+        source.addMetaData("version", flysVersion);
+
+        // FIXME
+        String user = "unbekannt";
+        // CSV_META_USER
+        source.addMetaData("user", user);
+        
+        final Locale locale = Resources.getLocale(context.getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        source.addMetaData("date", df.format(new Date()));
+
+        // CSV_META_RIVER
+        source.addMetaData("river", results.getRiver().getName());
+
+        // FIXME
+        source.addMetaData("range", "FIXME");
+        // "# Ort/Bereich (km): "
+        // FIXME
+        // TODO: unklar, es wird nur ein Bereich eingegeben
+//        RangeAccess rangeAccess = new RangeAccess(flys);
+//        double[] kms = rangeAccess.getKmRange();
+//        writer.writeNext(new String[] {
+//        		Resources.getMsg(
+//        				meta,
+//        				CSV_META_RANGE,
+//        				CSV_META_RANGE,
+//        				new Object[] { kms[0], kms[kms.length-1] })
+//        });
+
+//        RangeAccess rangeAccess = new RangeAccess(flys);
+//        double[] kms = rangeAccess.getKmRange();
+//        source.addMetaData("range",
+//                kmf.format(kms[0]) + " - " + kmf.format(kms[kms.length-1]));
+    }
+
+    private void addJRTableData(final MetaAndTableJRDataSource source, final FlowDepthCalculationResult result, final boolean useTkh) {
+    	
+    	final Collection<FlowDepthRow> rows = result.getRows();
+    	
+    	for (final FlowDepthRow row : rows) {
+    		
+    		final String[] formattedRow = formatFlowDepthRow(row, useTkh);
+    		source.addData(formattedRow);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthFilterFacet.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,98 @@
+/* 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.artifacts.sinfo.flowdepth;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+/**
+ * Facet of a FlowDepth curve.
+ */
+public class FlowDepthFilterFacet extends DataFacet {
+
+    private static Logger log = Logger.getLogger(FlowDepthFilterFacet.class);
+
+    public FlowDepthFilterFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public FlowDepthFilterFacet(
+        int         idx,
+        String      name,
+        String      description,
+        ComputeType type,
+        String      stateId,
+        String      hash
+    ) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "sinfo.chart.flow_depth.xaxis.label");
+        this.metaData.put("Y", "sinfo.chart.flow_depth.yaxis.label");
+    }
+
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        log.debug("Get data for flow velocity at index: " + index);
+
+        final D4EArtifact flys = (D4EArtifact) artifact;
+
+        final CalculationResult res = (CalculationResult)
+            flys.compute(context, hash, stateId, type, false);
+
+        final FlowDepthCalculationResults data = (FlowDepthCalculationResults) res.getData();
+        
+        final FlowDepthCalculationResult result = data.getResults().get(index);
+
+        // FIXME: variable mean computation depending on current scale
+//      Double start = (Double)context.getContextValue("startkm");
+//      Double end = (Double)context.getContextValue("endkm");
+//        if(start != null && end != null) {
+//            RiverContext fc = (RiverContext)context.globalContext();
+//            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+//            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+//            String river = access.getRiverName();
+//
+//            double radius = scales.getRadius(river, start, end);
+//            FlowVelocityData oldData = data[index];
+//            FlowVelocityData newData = new FlowVelocityData();
+//            double[][] q = oldData.getQPoints();
+//            double[][] totalV = MovingAverage.weighted(oldData.getTotalChannelPoints(), radius);
+//            double[][] mainV = MovingAverage.weighted(oldData.getMainChannelPoints(), radius);
+//            double[][] tau = MovingAverage.weighted(oldData.getTauPoints(), radius);
+//            for(int j = 0; j < q[0].length; j++) {
+//                newData.addKM(q[0][j]);
+//                newData.addQ(q[1][j]);
+//                newData.addTauMain(tau[1][j]);
+//                newData.addVMain(mainV[1][j]);
+//                newData.addVTotal(totalV[1][j]);
+//            }
+//            return newData;
+//        }
+
+      return result;
+    }
+
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        FlowDepthFilterFacet copy = new FlowDepthFilterFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type    = type;
+        copy.hash    = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthPairSelectState.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,27 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import org.dive4elements.river.artifacts.states.WaterlevelPairSelectState;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+public class FlowDepthPairSelectState
+// FIXME: very ugly; but probably we will break the serialization of WaterlevelPairSelectState if we introduce an abstraction 
+extends WaterlevelPairSelectState {
+
+    /** Specify to display a datacage_twin_panel. */
+    @Override
+    protected String getUIProvider() {
+        return "sinfo_flowdepth_twin_panel";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthProcessor.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,105 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.StyledSeriesBuilder;
+import org.dive4elements.river.exports.process.DefaultProcessor;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class FlowDepthProcessor extends DefaultProcessor {
+
+	/* Theme name, usually defined in 'FacetTypes', but that is soooo bad dependencies... */
+    static String FACET_FLOW_DEPTH_FILTERED = "sinfo_flow_depth.filtered";
+
+    private final static Logger log = Logger.getLogger(FlowDepthProcessor.class);
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth.section.yaxis.label";
+    private String yAxisLabel;
+
+    @Override
+    public void doOut(
+            final DiagramGenerator generator,
+            final ArtifactAndFacet bundle,
+            final ThemeDocument    theme,
+            final boolean          visible) {
+
+        final CallContext context = generator.getCallContext();
+        final Map<String, String> metaData = bundle.getFacet().getMetaData();
+        
+        final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+
+        yAxisLabel = metaData.get("Y");
+
+        final String facetName = bundle.getFacetName();
+        final FlowDepthCalculationResult data = (FlowDepthCalculationResult) bundle.getData(context);
+        if (data == null) {
+            // Check has been here before so we keep it for security reasons
+            // this should never happen though.
+            log.error("Data is null for facet: " + facetName);
+            return;
+        }
+        
+        final double [][] points = generatePoints(data);
+
+        StyledSeriesBuilder.addPoints(series, points, true);
+        generator.addAxisSeries(series, axisName, visible);
+    }
+
+    private static double[][] generatePoints(final FlowDepthCalculationResult data) {
+
+    	// FIXME
+    	return data.getFlowDepthPoints();
+
+//        if (facetName.equals(FacetTypes.FLOW_VELOCITY_TOTALCHANNEL) ||
+//                facetName.equals(FacetTypes.FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) {
+//            FlowVelocityData fData = (FlowVelocityData) data;
+//            points = fData.getTotalChannelPoints();
+//        } else if (facetName.equals(FacetTypes.FLOW_VELOCITY_MAINCHANNEL) ||
+//                facetName.equals(FacetTypes.FLOW_VELOCITY_MAINCHANNEL_FILTERED)) {
+//            FlowVelocityData fData = (FlowVelocityData) data;
+//            points = fData.getMainChannelPoints(); // I hate facets!
+//        } else if (facetName.equals(FacetTypes.FLOW_VELOCITY_MEASUREMENT)) {
+//            FastFlowVelocityMeasurementValue fData =
+//                (FastFlowVelocityMeasurementValue) data;
+//            points = new double[][] {{fData.getStation()},{fData.getV()}};
+//        } else {
+//            log.error("Unknown facet name: " + facetName);
+//            return;
+//        }
+	}
+
+	@Override
+    public boolean canHandle(String facettype) {
+        return FACET_FLOW_DEPTH_FILTERED.equals(facettype);
+    }
+
+    @Override
+    public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+        	// REMARK/UNINTENDED: yAxisLabel may also be a resolved message (side-effect of StyledXYSeries#putMetadata),
+        	// and cannot be resolved, so we need to give the resolved value as default
+        	// In other implementations (i.e. FlowVelocityProcessor), an explicit (German) default label is given here, probably
+        	// the English version will also show German (CHECK)
+            return generator.msg(yAxisLabel, yAxisLabel);
+        }
+        return generator.msg(
+                I18N_AXIS_LABEL,
+                "MISSING");
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthRow.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,90 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.flowdepth;
+
+import java.io.Serializable;
+
+/**
+ * Part of {@link FlowDepthCalculationResult} which represents one calculated row of flow depth data.
+ * 
+ * @author Gernot Belger
+ */
+final class FlowDepthRow
+implements Serializable {
+	private final double station;
+	private final double flowDepth;
+	private final double flowDepthWithTkh;
+	private final double tkh;
+	private final double waterlevel;
+	private final double discharge;
+	private final String waterlevelLabel;
+	private final String gauge;
+	private final double meanBedHeight;
+	private final String soundageLabel;
+	private final String location;
+
+	public FlowDepthRow( double station, double flowDepth, double flowDepthWithTkh, double tkh, double waterlevel, double discharge, String waterlevelLabel, String gauge, double meanBedHeight, String soundageLabel, String location ) {
+		this.station = station;
+		this.flowDepth = flowDepth;
+		this.flowDepthWithTkh = flowDepthWithTkh;
+		this.tkh = tkh;
+		this.waterlevel = waterlevel;
+		this.discharge = discharge;
+		this.waterlevelLabel = waterlevelLabel;
+		this.gauge = gauge;
+		this.meanBedHeight = meanBedHeight;
+		this.soundageLabel = soundageLabel;
+		this.location = location;
+	}
+
+	public double getStation() {
+		return station;
+	}
+
+	public double getFlowDepth() {
+		return flowDepth;
+	}
+
+	public double getFlowDepthWithTkh() {
+		return flowDepthWithTkh;
+	}
+	
+	public double getTkh() {
+		return tkh;
+	}
+
+	public double getWaterlevel() {
+		return waterlevel;
+	}
+
+	public double getDischarge() {
+		return discharge;
+	}
+
+	public String getWaterlevelLabel() {
+		return waterlevelLabel;
+	}
+
+	public String getGauge() {
+		return gauge;
+	}
+
+	public double getMeanBedHeight() {
+		return meanBedHeight;
+	}
+
+	public String getSoundageLabel() {
+		return soundageLabel;
+	}
+
+	public String getLocation() {
+		return location;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthState.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,140 @@
+/* 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.artifacts.sinfo.flowdepth;
+
+import java.util.List;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.ChartArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.EmptyFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.model.ReportFacet;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/** State in which a waterlevel has been calculated. */
+public class FlowDepthState
+extends      DefaultState
+{
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final String I18N_FACET_FLOW_DEPTH_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth.filtered.description";
+
+    /**
+     * From this state can only be continued trivially.
+     */
+    @Override
+    protected String getUIProvider() {
+        return "continue";
+    }
+
+    @Override
+    public Object computeFeed(
+        final D4EArtifact artifact,
+        final String       hash,
+        final CallContext  context,
+        final List<Facet>  facets,
+        final Object       old
+    ) {
+    	// FIXME: why is this necessary?
+        if (artifact instanceof ChartArtifact) {
+            facets.add(new EmptyFacet());
+            return null;
+        }
+        return compute((SINFOArtifact) artifact, context, hash, facets, old);
+    }
+
+    @Override
+    public Object computeAdvance(
+    	final D4EArtifact artifact,
+    	final String       hash,
+    	final CallContext  context,
+    	final List<Facet>  facets,
+    	final Object       old
+    ) {
+        if (artifact instanceof ChartArtifact) {
+            facets.add(new EmptyFacet());
+            return null;
+        }
+        return compute((SINFOArtifact) artifact, context, hash, facets, old);
+    }
+    
+    /**
+     * Compute result or returned object from cache, create facets.
+     * @param old Object that was cached.
+     */
+    private Object compute(
+    	final SINFOArtifact sinfo,
+        final CallContext   context,
+        final String        hash,
+        final List<Facet>   facets,
+        final Object        old
+    ) {
+        final CalculationResult res;
+		if (old instanceof CalculationResult)
+			res = (CalculationResult) old;
+		else
+			res = new FlowDepthCalculation(context).calculate(sinfo);
+
+        if (facets == null) {
+            return res;
+        }
+
+        final FlowDepthCalculationResults results =  (FlowDepthCalculationResults) res.getData();
+
+        /* add themes for chart, for each result */
+        final List<FlowDepthCalculationResult> resultList = results.getResults();
+        for (int index = 0; index < resultList.size(); index++) {
+
+			final FlowDepthCalculationResult result = resultList.get(index);
+			/* compute theme label */
+			final String wspLabel = result.getWstLabel();
+			final String soundingLabel = result.getSoundingLabel();
+			final String inputLabel = String.format("%s - %s", wspLabel, soundingLabel);
+			
+			/* filtered (zoom dependent mean) flow depth */
+			final String facetFlowDepthFilteredDescription = Resources.getMsg( context.getMeta(), I18N_FACET_FLOW_DEPTH_FILTERED_DESCRIPTION, I18N_FACET_FLOW_DEPTH_FILTERED_DESCRIPTION, inputLabel );
+			facets.add(new FlowDepthFilterFacet(
+			        index,
+			        FlowDepthProcessor.FACET_FLOW_DEPTH_FILTERED,
+			        facetFlowDepthFilteredDescription,
+			        ComputeType.ADVANCE,
+			        id,
+			        hash
+			    ));
+			
+			// FIXME: add other themes
+		}
+
+        if (!resultList.isEmpty() ) {
+            Facet csv = new DataFacet(
+                FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, id);
+            Facet pdf = new DataFacet(
+            		FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, id);
+
+            facets.add(csv);
+            facets.add(pdf);
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems()) {
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id));
+        }
+
+        return res;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/UseTransportBodiesChoice.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,21 @@
+/* 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.artifacts.sinfo.flowdepth;
+
+import org.dive4elements.river.artifacts.states.BooleanChoiceState;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class UseTransportBodiesChoice extends BooleanChoiceState {
+
+    public UseTransportBodiesChoice() {
+    	super( "useTransportBodies.option", "useTransportBodies.active", "useTransportBodies.inactive" );
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/util/MetaAndTableJRDataSource.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,64 @@
+/* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.artifacts.sinfo.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.jasperreports.engine.JRDataSource;
+import net.sf.jasperreports.engine.JRException;
+import net.sf.jasperreports.engine.JRField;
+
+/**
+ * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
+ */
+public final class MetaAndTableJRDataSource implements JRDataSource
+{
+    private List<String[]> data = new ArrayList<>();
+
+    private Map<String, String> metaData = new HashMap<>();
+
+    private int index = -1;
+
+    public void addData(final String[] data) {
+        this.data.add(data);
+    }
+
+    public void addMetaData(final String key, final String value) {
+        this.metaData.put(key, value);
+    }
+
+    @Override
+	public boolean next() throws JRException
+    {
+        index++;
+
+        return index < data.size();
+    }
+
+    @Override
+	public Object getFieldValue(final JRField field) throws JRException
+    {
+        final String fieldName = field.getName();
+        
+        if( fieldName.startsWith("meta:"))
+        	return metaData.get(fieldName.substring("meta:".length()));
+
+        if( fieldName.startsWith("data:"))
+        {
+        	int column = Integer.valueOf(fieldName.substring("data:".length()));
+        	return data.get(index)[column];
+        }
+        
+        return null;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/resources/messages.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/src/main/resources/messages.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -761,3 +761,65 @@
 help.state.fix.vollmer.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.preprocessing
 help.state.fix.vollmer.qs=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.qs
 help.state.fix.vollmer.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.compute
+
+state.sinfo.river = River
+state.sinfo.calculation_mode=Calculation Mode
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_grounding=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_infrastructures_inundation_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+help.state.sinfo=${help.url}/OnlineHilfe/SINFO
+help.state.sinfo.river=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.river
+help.state.sinfo.calculation_mode=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.calculation_mode
+
+state.sinfo.distance_only = Range selection
+help.state.sinfo.distance_only=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only
+
+state.sinfo.waterlevel_soundings_select= Chosen Differences
+help.state.sinfo.waterlevel_soundings_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_select
+
+state.sinfo.use_transport_bodies=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.use_transport_bodies=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.use_transport_bodies
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Activ
+useTransportBodies.inactive = Inactiv
+
+sinfo.export.flow_depth.csv.meta.header.result = ## Calculation Output - {0} - Flie\u00dftiefe - FLYS 3
+sinfo.export.flow_depth.csv.meta.version = # FLYS-Version: {0}
+sinfo.export.flow_depth.csv.meta.user = # Bearbeiter: {0}
+sinfo.export.flow_depth.csv.meta.creation = # Time of creation: {0}
+sinfo.export.flow_depth.csv.meta.river = # River: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+
+#export.export.flow_depth.csv.meta.range = # Location/Range (km): {0} - {1}
+#export.export.flow_depth.csv.meta.gauge = # Gauge: {0}
+#export.export.flow_depth.csv.meta.q = # Q (m\u00b3/s): {0}
+#export.export.flow_depth.csv.meta.w = # W (NN + m): {0} - {1}
+
+sinfo.export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe [m]
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH [m]
+sinfo.export.flow_depth.csv.header.tkh = Flie\u00dftiefe mit TKH [cm]
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand [NN+m]
+sinfo.export.flow_depth.csv.header.discharge = Q [m\u00b3/s]
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he [NN+m]
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.flow_depth.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flie\u00dftiefe h [m]
+sinfo.facet.flow_depth.filtered.description = Flie\u00dftiefe ({0}) 
--- a/artifacts/src/main/resources/messages_de.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/src/main/resources/messages_de.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -36,10 +36,10 @@
 state.fix.analysis.referenceperiod = Bezugszeitraum
 state.fix.analysis.analysisperiods = Analysezeitr\u00e4ume
 state.fix.analysis.function = Ausgleichsfunktion
-state.fix.analysis.preprocessing = Ausrei\u00DFer
+state.fix.analysis.preprocessing = Ausrei\u00dfer
 state.fix.preprocess=Ausrei\u00dfertest durchf\u00fchren
 state.fix.vollmer.function= Ausgleichsfunktion
-state.fix.vollmer.preprocessing = Ausrei\u00DFer
+state.fix.vollmer.preprocessing = Ausrei\u00dfer
 state.fix.vollmer.qs = Eingabe f\u00fcr W/Q Daten
 
 state.minfo.river = Gew\u00e4sser
@@ -286,7 +286,7 @@
 facet.sedimentload.calc.bed_load = Geschiebefracht (Berechnung FLYS) - {0} [{1}]
 facet.sedimentload.calc.bed_load_susp_sand = bettbildende Fracht (Berechnung FLYS) - {0} [{1}]
 
-minfo.sedimentload.no.data = Keine Sedimentfracht-Daten verfügbar
+minfo.sedimentload.no.data = Keine Sedimentfracht-Daten verf\u00fcgbar
 sedimentload.missing.fraction.coarse = Fehlende Fraktion Grober Kies/Steine - {0}
 sedimentload.missing.fraction.fine_middle = Fehlende Fraktion Fein/Mittlerer Kies - {0}
 sedimentload.missing.fraction.sand = Fehlende Fraktion Sand - {0}
@@ -730,6 +730,7 @@
 static.sq.station = Messstelle
 
 module.winfo = W-INFO
+module.sinfo = S-INFO
 module.minfo = M-INFO
 module.fixanalysis = Fixierungsanalyse
 module.new_map = Neue Karte
@@ -766,3 +767,65 @@
 help.state.fix.vollmer.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.preprocessing
 help.state.fix.vollmer.qs=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.qs
 help.state.fix.vollmer.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.compute
+
+state.sinfo.river = Gew\u00e4sser
+state.sinfo.calculation_mode=Berechnungsart
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_grounding=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_infrastructures_inundation_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+help.state.sinfo=${help.url}/OnlineHilfe/SINFO
+help.state.sinfo.river=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.river
+help.state.sinfo.calculation_mode=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.calculation_mode
+
+state.sinfo.distance_only = Wahl der Berechnungsstrecke
+help.state.sinfo.distance_only=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only
+
+state.sinfo.waterlevel_soundings_select= Ausgew\u00e4hlte Differenzen
+help.state.sinfo.waterlevel_soundings_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_select
+
+state.sinfo.use_transport_bodies=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.use_transport_bodies=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.use_transport_bodies
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Aktiv
+useTransportBodies.inactive = Inaktiv
+
+sinfo.export.flow_depth.csv.meta.header.result = ## Ergebnisausgabe - {0} - Flie\u00dftiefe - FLYS 3
+sinfo.export.flow_depth.csv.meta.version = # FLYS-Version: {0}
+sinfo.export.flow_depth.csv.meta.user = # Bearbeiter: {0}
+sinfo.export.flow_depth.csv.meta.creation = # Datum der Erstellung: {0}
+sinfo.export.flow_depth.csv.meta.river = # Gew\u00e4sser: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+
+#export.export.flow_depth.csv.meta.range = # Location/Range (km): {0} - {1}
+#export.export.flow_depth.csv.meta.gauge = # Gauge: {0}
+#export.export.flow_depth.csv.meta.q = # Q (m\u00b3/s): {0}
+#export.export.flow_depth.csv.meta.w = # W (NN + m): {0} - {1}
+
+sinfo.export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe [m]
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH [m]
+sinfo.export.flow_depth.csv.header.tkh = Flie\u00dftiefe mit TKH [cm]
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand [NN+m]
+sinfo.export.flow_depth.csv.header.discharge = Q [m\u00b3/s]
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he [NN+m]
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.flow_depth.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flow Depth h [m]
+sinfo.facet.flow_depth.filtered.description = Flie\u00dftiefe ({0}) 
\ No newline at end of file
--- a/artifacts/src/main/resources/messages_de_DE.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/src/main/resources/messages_de_DE.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -36,10 +36,10 @@
 state.fix.analysis.referenceperiod = Bezugszeitraum
 state.fix.analysis.analysisperiods = Analysezeitr\u00e4ume
 state.fix.analysis.function = Ausgleichsfunktion
-state.fix.analysis.preprocessing = Ausrei\u00DFer
+state.fix.analysis.preprocessing = Ausrei\u00dfer
 state.fix.preprocess=Ausrei\u00dfertest durchf\u00fchren
 state.fix.vollmer.function= Ausgleichsfunktion
-state.fix.vollmer.preprocessing = Ausrei\u00DFer
+state.fix.vollmer.preprocessing = Ausrei\u00dfer
 state.fix.vollmer.qs = Eingabe f\u00fcr W/Q Daten
 
 state.minfo.river = Gew\u00e4sser
@@ -283,7 +283,7 @@
 facet.sedimentload.calc.bed_load = Geschiebefracht (Berechnung FLYS) - {0} [{1}]
 facet.sedimentload.calc.bed_load_susp_sand = bettbildende Fracht (Berechnung FLYS) - {0} [{1}]
 
-minfo.sedimentload.no.data = Keine Sedimentfracht-Daten verfügbar
+minfo.sedimentload.no.data = Keine Sedimentfracht-Daten verf\u00fcgbar
 sedimentload.missing.fraction.coarse = Fehlende Fraktion Grober Kies/Steine - {0}
 sedimentload.missing.fraction.fine_middle = Fehlende Fraktion Fein/Mittlerer Kies - {0}
 sedimentload.missing.fraction.sand = Fehlende Fraktion Sand - {0}
@@ -763,3 +763,65 @@
 help.state.fix.vollmer.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.preprocessing
 help.state.fix.vollmer.qs=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.qs
 help.state.fix.vollmer.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.compute
+
+state.sinfo.river = Gew\u00e4sser
+state.sinfo.calculation_mode=Berechnungsart
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_grounding=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_infrastructures_inundation_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+help.state.sinfo=${help.url}/OnlineHilfe/SINFO
+help.state.sinfo.river=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.river
+help.state.sinfo.calculation_mode=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.calculation_mode
+
+state.sinfo.distance_only = Wahl der Berechnungsstrecke
+help.state.sinfo.distance_only=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only
+
+state.sinfo.waterlevel_soundings_select= Ausgew\u00e4hlte Differenzen
+help.state.sinfo.waterlevel_soundings_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_select
+
+state.sinfo.use_transport_bodies=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.use_transport_bodies=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.use_transport_bodies
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Aktiv
+useTransportBodies.inactive = Inaktiv
+
+sinfo.export.flow_depth.csv.meta.header.result = ## Ergebnisausgabe - {0} - Flie\u00dftiefe - FLYS 3
+sinfo.export.flow_depth.csv.meta.version = # FLYS-Version: {0}
+sinfo.export.flow_depth.csv.meta.user = # Bearbeiter: {0}
+sinfo.export.flow_depth.csv.meta.creation = # Datum der Erstellung: {0}
+sinfo.export.flow_depth.csv.meta.river = # Gew\u00e4sser: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+
+#export.export.flow_depth.csv.meta.range = # Location/Range (km): {0} - {1}
+#export.export.flow_depth.csv.meta.gauge = # Gauge: {0}
+#export.export.flow_depth.csv.meta.q = # Q (m\u00b3/s): {0}
+#export.export.flow_depth.csv.meta.w = # W (NN + m): {0} - {1}
+
+sinfo.export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe [m]
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH [m]
+sinfo.export.flow_depth.csv.header.tkh = Flie\u00dftiefe mit TKH [cm]
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand [NN+m]
+sinfo.export.flow_depth.csv.header.discharge = Q [m\u00b3/s]
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he [NN+m]
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.flow_depth.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flow Depth h [m]
+sinfo.facet.flow_depth.filtered.description = Flie\u00dftiefe ({0}) 
\ No newline at end of file
--- a/artifacts/src/main/resources/messages_en.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/artifacts/src/main/resources/messages_en.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -762,3 +762,65 @@
 help.state.fix.vollmer.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.preprocessing
 help.state.fix.vollmer.qs=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.qs
 help.state.fix.vollmer.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.compute
+
+state.sinfo.river = River
+state.sinfo.calculation_mode=Calculation Mode
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_grounding=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_infrastructures_inundation_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+help.state.sinfo=${help.url}/OnlineHilfe/SINFO
+help.state.sinfo.river=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.river
+help.state.sinfo.calculation_mode=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.calculation_mode
+
+state.sinfo.distance_only = Range selection
+help.state.sinfo.distance_only=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only
+
+state.sinfo.waterlevel_soundings_select= Chosen Differences
+help.state.sinfo.waterlevel_soundings_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_select
+
+state.sinfo.use_transport_bodies=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.use_transport_bodies=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.use_transport_bodies
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Activ
+useTransportBodies.inactive = Inactiv
+
+sinfo.export.flow_depth.csv.meta.header.result = ## Calculation Output - {0} - Flie\u00dftiefe - FLYS 3
+sinfo.export.flow_depth.csv.meta.version = # FLYS-Version: {0}
+sinfo.export.flow_depth.csv.meta.user = # Bearbeiter: {0}
+sinfo.export.flow_depth.csv.meta.creation = # Time of creation: {0}
+sinfo.export.flow_depth.csv.meta.river = # River: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+
+#export.export.flow_depth.csv.meta.range = # Location/Range (km): {0} - {1}
+#export.export.flow_depth.csv.meta.gauge = # Gauge: {0}
+#export.export.flow_depth.csv.meta.q = # Q (m\u00b3/s): {0}
+#export.export.flow_depth.csv.meta.w = # W (NN + m): {0} - {1}
+
+sinfo.export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe [m]
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH [m]
+sinfo.export.flow_depth.csv.header.tkh = Flie\u00dftiefe mit TKH [cm]
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand [NN+m]
+sinfo.export.flow_depth.csv.header.discharge = Q [m\u00b3/s]
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+# FIXME: H\u00f6henbezugssystem?
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he [NN+m]
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.flow_depth.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flie\u00dftiefe h [m]
+sinfo.facet.flow_depth.filtered.description = Flie\u00dftiefe ({0}) 
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Thu Jan 18 18:34:41 2018 +0100
@@ -1421,5 +1421,15 @@
     String error_no_sedimentloadinfo_found();
 
     String error_no_sedimentloadinfo_data();
+
+    String sinfo();
+    
+    String sinfo_flowdepth_export();
+
+    String sinfo_flowdepth_report();
+
+    String sinfo_flow_depth();
+
+	String sinfo_flowdepth_twinpanel_no_pair_selected();
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -756,3 +756,9 @@
 upper_time = to
 
 no_data_for_year = No data available for: $1
+
+sinfo = S-INFO
+sinfo_flowdepth_export = Flie\u00dftiefen Export
+sinfo_flowdepth_report = Flie\u00dftiefen Bericht
+sinfo_flow_depth = Flie\u00dftiefen
+sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -748,3 +748,9 @@
 upper_time = bis
 
 no_data_for_year = F\u00fcr das Jahr $1 liegen keine Daten vor.
+
+sinfo = S-INFO
+sinfo_flowdepth_export = Flie\u00dftiefen Export
+sinfo_flowdepth_report = Flie\u00dftiefen Bericht
+sinfo_flow_depth = Flie\u00dftiefen
+sinfo_flowdepth_twinpanel_no_pair_selected = Fehler - kein Paar zur Differenzenbildung gew\u00e4hlt.
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Thu Jan 18 18:34:41 2018 +0100
@@ -785,3 +785,9 @@
 upper_time = to
 
 no_data_for_year = No data available for: $1
+
+sinfo = S-INFO
+sinfo_flowdepth_export = Flie\u00dftiefen Export
+sinfo_flowdepth_report = Flie\u00dftiefen Bericht
+sinfo_flow_depth = Flie\u00dftiefen
+sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java	Thu Jan 18 18:34:41 2018 +0100
@@ -65,6 +65,7 @@
 import org.dive4elements.river.client.shared.model.OutputMode;
 import org.dive4elements.river.client.shared.model.ReportMode;
 import org.dive4elements.river.client.shared.model.River;
+import org.dive4elements.river.client.shared.model.SINFOArtifact;
 import org.dive4elements.river.client.shared.model.WINFOArtifact;
 
 import java.util.ArrayList;
@@ -770,8 +771,11 @@
                 setCurrentData(null, null);
             }
         }
+
+        // FIXME: we got a whole artifact framework to separate ui and backend stuff, but in the end.... we have switches over specific datatypes here...
         if (art instanceof WINFOArtifact
-                || art instanceof FixAnalysisArtifact) {
+            || art instanceof SINFOArtifact
+        	|| art instanceof FixAnalysisArtifact) {
             createGaugePanel();
             renderInfo(desc.getRiver(), desc.getOldData());
         }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java	Thu Jan 18 18:34:41 2018 +0100
@@ -22,6 +22,7 @@
 import org.dive4elements.river.client.client.ui.minfo.SedLoadEpochPanel;
 import org.dive4elements.river.client.client.ui.minfo.SedLoadPeriodPanel;
 import org.dive4elements.river.client.client.ui.minfo.SedLoadSQTiPanel;
+import org.dive4elements.river.client.client.ui.sinfo.FlowDepthTwinPanel;
 import org.dive4elements.river.client.client.ui.sq.SQPeriodPanel;
 import org.dive4elements.river.client.shared.model.User;
 
@@ -86,8 +87,8 @@
         else if (uiProvider.equals("dgm_datacage_panel")) {
             return new DemDatacagePanel(user);
         }
-        else if (uiProvider.equals("datacage_twin_panel")) {
-            return new DatacageTwinPanel(user);
+        else if (uiProvider.equals("waterlevel_twin_panel")) {
+            return new WaterlevelTwinPanel(user);
         }
         else if (uiProvider.equals("auto_integer")) {
             return new AutoIntegerPanel();
@@ -194,10 +195,12 @@
         else if (uiProvider.equals("static_sqrelation")) {
             return new StaticDataPanel();
         }
-        else {
-            //GWT.log("Picked default provider.");
-            return new SelectProvider();
-        }
+        
+        if ("sinfo_flowdepth_twin_panel".equals(uiProvider))
+        	return new FlowDepthTwinPanel(user);
+
+        //GWT.log("Picked default provider.");
+        return new SelectProvider();
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/FlowDepthTwinPanel.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,25 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.client.client.ui.sinfo;
+
+import org.dive4elements.river.client.client.ui.DatacageTwinPanel;
+import org.dive4elements.river.client.client.ui.DefaultDatacageTwinPanelInfo;
+import org.dive4elements.river.client.client.ui.WaterlevelRecommandationInfo;
+import org.dive4elements.river.client.shared.model.User;
+
+/**
+ * @author Gernot Belger
+ */
+public class FlowDepthTwinPanel 
+extends DatacageTwinPanel {
+	public FlowDepthTwinPanel(final User user) {
+		super(user, new FlowDepthTwinPanelValidator(), new WaterlevelRecommandationInfo("sinfo_flowdepth_waterlevels"), new DefaultDatacageTwinPanelInfo("bedheight", "sinfo_flowdepth_minfo_heights") );
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/FlowDepthTwinPanelValidator.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,39 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by 
+ *  Björnsen Beratende Ingenieure GmbH 
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.client.client.ui.sinfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.ui.AbstractPairRecommendationPanel.IValidator;
+
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+/**
+ * Contains the old code from the validate-method of the DatacageTwinPanel.
+ *  
+ * @author Gernot Belger
+ */
+final class FlowDepthTwinPanelValidator implements IValidator {
+
+	@Override
+	public List<String> validate(final ListGrid differencesList, final FLYSConstants msgProvider) {
+
+        final List<String> errors = new ArrayList<String>();
+        if (differencesList.getRecords().length == 0) {
+        	// FIXME: waterlevel dependent! This will lead to a bad error message in English, for M-Info/Bed-Differences calculation
+            errors.add(msgProvider.sinfo_flowdepth_twinpanel_no_pair_selected());
+        }
+
+        return errors;
+	}
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/FLYSArtifactCreator.java	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/FLYSArtifactCreator.java	Thu Jan 18 18:34:41 2018 +0100
@@ -31,6 +31,7 @@
 import org.dive4elements.river.client.shared.model.FixAnalysisArtifact;
 import org.dive4elements.river.client.shared.model.GaugeDischargeCurveArtifact;
 import org.dive4elements.river.client.shared.model.MapArtifact;
+import org.dive4elements.river.client.shared.model.SINFOArtifact;
 import org.dive4elements.river.client.shared.model.MINFOArtifact;
 import org.dive4elements.river.client.shared.model.StaticSQRelationArtifact;
 import org.dive4elements.river.client.shared.model.WINFOArtifact;
@@ -134,35 +135,47 @@
 
         name = name.trim();
 
-        if (name.length() > 0 && name.equals("winfo")) {
+        // FIXME: why do we have a super sophisticated artifact-framework if, in the end, module dependent stuff is still switched manually....
+        if (name.equals("winfo")) {
             log.debug("+++++ NEW WINFO ARTIFACT.");
             return new WINFOArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("new_map")) {
+
+        if (name.equals("new_map")) {
             log.debug("+++++ NEW MAP ARTIFACT.");
             return new MapArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("new_chart")) {
+        
+        if (name.equals("new_chart")) {
             log.debug("+++++ NEW CHART ARTIFACT.");
             return new ChartArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("minfo")) {
+        
+        if (name.equals("minfo")) {
             log.debug("+++++ NEW MINFO ARTIFACT.");
             return new MINFOArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("fixanalysis")) {
+        
+        if (name.equals("fixanalysis")) {
             log.debug("+++++ NEW FIXANALYSIS ARTIFACT.");
             return new FixAnalysisArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("gaugedischargecurve")) {
+        
+        if (name.equals("gaugedischargecurve")) {
             log.debug("+++++ NEW GAUGEDISCHARGECURVE ARTIFACT.");
             return new GaugeDischargeCurveArtifact(uuid, hash, background, msg);
         }
-        else if (name.length() > 0 && name.equals("staticsqrelation")) {
+        
+        if (name.equals("staticsqrelation")) {
             log.debug("+++++ STATICSQRELATION ARTIFACT.");
             return new StaticSQRelationArtifact(uuid, hash, background, msg);
         }
 
+        if (name.equals("sinfo")) {
+            log.debug("+++++ NEW SINFO ARTIFACT.");
+            return new SINFOArtifact(uuid, hash, background, msg);
+        }
+
         return new DefaultArtifact(uuid, hash, background, msg);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SINFOArtifact.java	Thu Jan 18 18:34:41 2018 +0100
@@ -0,0 +1,46 @@
+/* Copyright (C) 2017 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.client.shared.model;
+
+import java.util.List;
+
+
+/**
+ * The SINFO implementation of an Artifact.
+ *
+ * @author Gernot Belger
+ */
+public class SINFOArtifact extends DefaultArtifact {
+
+    /** The name of this artifact: 'sinfo'.*/
+    private static final String NAME = "sinfo";
+
+    /** Necessary for serialization */
+    public SINFOArtifact() {
+    }
+
+//    public  SINFOArtifact(String uuid, String hash) {
+//        super(uuid, hash);
+//    }
+
+    public SINFOArtifact(
+        String                   uuid,
+        String                   hash,
+        boolean                  inBackground,
+        List<CalculationMessage> messages
+    ) {
+        super(uuid, hash, inBackground, messages);
+    }
+
+
+    public String getName() {
+        return NAME;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/webapp/WEB-INF/features.xml	Thu Jan 18 18:33:52 2018 +0100
+++ b/gwt-client/src/main/webapp/WEB-INF/features.xml	Thu Jan 18 18:34:41 2018 +0100
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ftr:features xmlns:ftr="http://www.intevation.de/2012/flys/features">
     <ftr:role name="d4e_demo_all">
+        <ftr:feature>module:sinfo</ftr:feature>
         <ftr:feature>module:winfo</ftr:feature>
         <ftr:feature>module:minfo</ftr:feature>
         <ftr:feature>module:new_map</ftr:feature>

http://dive4elements.wald.intevation.org